from operator import truediv
import tkinter as tk
from tkinter import ttk, messagebox, filedialog, simpledialog
import sqlite3
from datetime import datetime, timedelta
import os
from auth import PasswordDialog
from total_water_meter import TotalWaterMeterDialog
# 尝试导入openpyxl库，如果不存在则提供友好提示
try:
    import openpyxl
    from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
    OPENPYXL_AVAILABLE = True
except ImportError:
    OPENPYXL_AVAILABLE = False

# 导入webbrowser用于自动打开Excel文件
import webbrowser

# 尝试导入matplotlib库用于生成图表
try:
    import matplotlib.pyplot as plt
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
    MATPLOTLIB_AVAILABLE = True
except ImportError:
    MATPLOTLIB_AVAILABLE = False

class MainUI:
    def __init__(self, root, manager):
        self.root = root
        self.manager = manager
        self.auth = None  # 认证对象将从manager传入
        # 预初始化系统设置页面相关属性
        self.price_frame = None
        self.price_tab_loaded = False
        self.setup_ui()
    
    def update_current_user_label(self):
        """更新当前登录用户信息标签"""
        if hasattr(self, 'current_user_label'):
            if self.auth and self.auth.get_current_user():
                username = self.auth.get_current_user()
                self.current_user_label.config(text=f"当前登录用户：{username}", style='Secondary.TLabel')
            else:
                # 如果没有认证对象或当前用户，则显示默认的管理员用户
                self.current_user_label.config(text="当前登录用户：admin", style='Secondary.TLabel')
    
    def verify_password(self, purpose="执行此操作"):
        """验证用户密码 - 使用当前登录用户的凭证进行验证"""
        try:
            print(f"开始验证密码，用途: {purpose}")
            
            # 使用tkinter内置的密码对话框
            from tkinter import simpledialog
            password = simpledialog.askstring("密码验证", 
                                             f"请输入密码以{purpose}:", 
                                             show="*")
            
            # 如果用户取消或密码为空，验证失败
            if not password:
                print("密码验证失败：用户取消或密码为空")
                return False
            
            # 获取当前登录用户
            current_username = None
            if self.auth and self.auth.get_current_user():
                current_username = self.auth.get_current_user()
            else:
                # 默认使用admin用户（向后兼容）
                current_username = "admin"
            
            # 使用当前登录用户的凭证进行密码验证
            if self.auth and hasattr(self.auth, 'verify_password'):
                # 使用auth对象的verify_password方法验证当前用户密码
                is_verified = self.auth.verify_password(current_username, password)
            elif self.auth and hasattr(self.auth, 'verify_user'):
                # 兼容旧版本的验证方法
                is_verified = self.auth.verify_user(current_username, password)
            else:
                # 为确保安全性，如果无法使用auth对象验证，则验证失败
                print("密码验证失败：无法获取有效的认证对象")
                return False
                
            if is_verified:
                print("密码验证成功")
                return True
            else:
                print("密码验证失败：密码不正确")
                return False
        except Exception as e:
            print(f"密码验证过程中发生错误: {str(e)}")
            return False
        
        return is_verified
    
    def show_total_water_meter(self):
        """
        显示总水表抄数对话框
        获取当前选择的月份，并打开总水表抄数记录窗口
        """
        try:
            # 获取当前选择的月份
            current_month = self.reading_month_combo.get()
            if not current_month:
                # 如果没有选择月份，使用当前月份
                current_month = datetime.now().strftime("%Y-%m")
                # 设置到下拉框中
                self.reading_month_combo.set(current_month)
            
            # 打开总水表抄数对话框
            dialog = TotalWaterMeterDialog(self.root, current_month)
            dialog.show_dialog()
        except Exception as e:
            print(f"打开总水表抄数对话框时发生错误: {str(e)}")
            messagebox.showerror("错误", f"无法打开总水表抄数对话框: {str(e)}")
        except Exception as e:
            print(f"密码验证过程中发生错误: {str(e)}")
            # 出错时也返回False
            return False
        
    def setup_ui(self):
        """设置主界面"""
        # 创建样式
        style = ttk.Style()
        
        # 现代主题颜色方案 - 淡绿色主题
        primary_color = '#4caf50'  # 主色调-淡绿色
        primary_dark = '#388e3c'   # 深绿色
        primary_light = '#e8f5e9'  # 浅淡绿色
        success_color = '#66bb6a'  # 成功色-浅绿色
        warning_color = '#fbbc05'  # 警告色-黄色
        error_color = '#f44336'    # 错误色-红色
        text_color = '#202124'     # 主文本色
        text_secondary = '#5f6368' # 次要文本色
        bg_color = '#ffffff'       # 背景色
        bg_secondary = '#f1f8e9'   # 次要背景色-极浅淡绿色
        border_color = '#c8e6c9'   # 边框色-淡绿色
        
        # 设置整体主题样式
        style.theme_use('clam')  # 选择一个现代风格的主题基础
        
        # 框架样式
        style.configure('TFrame', background=bg_color)
        style.configure('Card.TFrame', background=bg_color, borderwidth=1, relief='solid', bordercolor=border_color)
        
        # 标签样式
        style.configure('TLabel', background=bg_color, font=('微软雅黑', 10), foreground=text_color)
        style.configure('Header.TLabel', font=('微软雅黑', 16, 'bold'), foreground=primary_color, background=bg_color)
        style.configure('SubHeader.TLabel', font=('微软雅黑', 12, 'bold'), foreground=text_color, background=bg_color)
        style.configure('Feature.TLabel', font=('微软雅黑', 10), foreground=text_color, background=bg_color)
        style.configure('Secondary.TLabel', font=('微软雅黑', 9), foreground=text_secondary, background=bg_color)
        
        # 按钮样式
        style.configure('TButton', font=('微软雅黑', 10), padding=6)
        style.configure('Primary.TButton', font=('微软雅黑', 10), foreground='white', background=primary_color)
        style.map('Primary.TButton', background=[('active', primary_dark)])
        
        # 标签框架样式
        style.configure('TLabelframe', background=bg_color, borderwidth=1, bordercolor=border_color, padding=10)
        style.configure('TLabelframe.Label', font=('微软雅黑', 10, 'bold'), foreground=text_color, background=bg_color)
        
        # 输入框样式
        style.configure('TEntry', font=('微软雅黑', 10), padding=3, borderwidth=1, bordercolor=border_color)
        
        # 下拉框样式
        style.configure('TCombobox', font=('微软雅黑', 10), padding=3)
        
        # 表格样式美化
        style.configure('Treeview', font=('微软雅黑', 10), rowheight=25, background=bg_color, foreground=text_color)
        style.configure('Treeview.Heading', font=('微软雅黑', 10, 'bold'), background=primary_light, foreground=primary_color, padding=5)
        style.map('Treeview', background=[('selected', primary_color), ('!selected', bg_color)])
        style.map('Treeview', foreground=[('selected', 'white'), ('!selected', text_color)])
        # 设置表格行的交替背景色
        style.configure('Treeview.Row', background=bg_color)
        style.configure('Treeview.AlternatingRow', background=bg_secondary)
        
        # 设置窗口样式
        self.root.configure(bg='#ffffff')
        
        # 主框架 - 使用卡片样式，增加视觉层次感
        main_frame = ttk.Frame(self.root, style='Card.TFrame')
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # 顶部区域 - 包含用户信息和标题
        top_section = ttk.Frame(main_frame)
        top_section.pack(fill=tk.X, pady=(0, 20))
        
        # 用户信息区域
        user_info_frame = ttk.Frame(top_section)
        user_info_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 当前登录用户信息（右对齐）
        self.current_user_label = ttk.Label(user_info_frame, text="当前登录用户：", style='Secondary.TLabel')
        self.current_user_label.pack(side=tk.RIGHT, padx=20)
        
        # 标题区域
        header_frame = ttk.Frame(top_section)
        header_frame.pack(fill=tk.X)
        
        # 从数据库获取软件信息
        software_info = self.get_software_info()
        brand = software_info.get('brand', '')
        name = software_info.get('name', '吾已水电费管理系统')
        version = software_info.get('version', 'v1.5')
        
        # 构建标题文本
        if brand:
            title_text = f"{brand}{name}"
        else:
            title_text = name
        
        # 标题（水平居中）
        header_label = ttk.Label(header_frame, text=title_text, style='Header.TLabel')
        header_label.pack(fill=tk.X, pady=10)
        header_label.config(anchor=tk.CENTER)
        
        # 添加版本信息标签
        version_label = ttk.Label(header_frame, text=f"版本 {version}", style='Secondary.TLabel')
        version_label.pack(fill=tk.X)
        version_label.config(anchor=tk.CENTER)
        
        # 尝试更新当前登录用户信息
        self.update_current_user_label()
        
        # 创建选项卡 - 使用自定义样式美化
        self.notebook = ttk.Notebook(main_frame)
        self.notebook.pack(fill=tk.BOTH, expand=True, pady=(10, 0))
        
        # 美化标签页样式
        style.configure('TNotebook', background=bg_color, tabmargins=0)
        style.configure('TNotebook.Tab', font=('微软雅黑', 10, 'bold'), padding=(15, 8), background=bg_secondary, foreground=text_secondary)
        style.map('TNotebook.Tab', background=[('selected', bg_color)], foreground=[('selected', primary_color)])
        
        # 绑定选项卡切换事件
        self.notebook.bind("<<NotebookTabChanged>>", self.on_tab_changed)
        
        # 添加各个功能页面 - 关于页面放在最后面
        self.setup_reading_tab()
        self.setup_payment_tab()
        self.setup_report_tab()
        self.setup_property_tab()
        self.setup_price_tab()
        self.setup_about_tab()
        
    def on_tab_changed(self, event):
        """选项卡切换事件处理"""
        # 由于环境限制，系统设置页面内容已在setup_price_tab中直接加载
        # 此方法保留用于未来可能的功能扩展
        pass
        
    def load_price_tab_content(self):
        """加载系统设置页面内容"""
        if not hasattr(self, 'price_frame') or self.price_tab_loaded:
            return
        
        # 清空框架内的所有内容
        for widget in self.price_frame.winfo_children():
            widget.destroy()
        
        # 创建收费标准相关功能的父框架 - 使用卡片样式
        price_management_frame = ttk.LabelFrame(self.price_frame, text="收费标准管理", padding=15, style='Card.TFrame')
        price_management_frame.pack(fill=tk.BOTH, expand=False, padx=10, pady=10)
        
        # 创建一个垂直框架，作为所有收费标准相关元素的容器
        price_content_frame = ttk.Frame(price_management_frame)
        price_content_frame.pack(fill=tk.BOTH, expand=False)
        
        # ========= 收费标准管理区域 - 所有三个模块在同一行显示 =========
        all_sections_frame = ttk.Frame(price_content_frame)
        all_sections_frame.pack(fill=tk.BOTH, expand=False, pady=(0, 10))
        
        # 收费标准类型框架 - 放置在左侧，设置固定宽度
        type_frame = ttk.LabelFrame(all_sections_frame, text="收费标准类型", padding=10, style='Card.TFrame')
        type_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 6))
        
        # -------- 收费标准类型框架内容 --------
        ttk.Label(type_frame, text="选择类型:").grid(row=0, column=0, padx=4, pady=6, sticky=tk.W)
        self.price_type_combo = ttk.Combobox(type_frame, width=14)
        self.price_type_combo.grid(row=0, column=1, padx=4, pady=6)
        
        ttk.Label(type_frame, text="新增类型:").grid(row=1, column=0, padx=4, pady=6, sticky=tk.W)
        self.new_type_entry = ttk.Entry(type_frame, width=14)
        self.new_type_entry.grid(row=1, column=1, padx=4, pady=6)
        
        ttk.Button(type_frame, text="添加类型", command=self.add_price_type).grid(row=2, column=0, padx=4, pady=8, columnspan=2, sticky=tk.EW)
        ttk.Button(type_frame, text="删除类型", command=self.delete_price_type).grid(row=3, column=0, padx=4, pady=4, columnspan=2, sticky=tk.EW)
        
        # 价格配置框架 - 放置在中间，设置固定宽度
        config_frame = ttk.LabelFrame(all_sections_frame, text="价格配置", padding=10, style='Card.TFrame')
        config_frame.pack(side=tk.LEFT, fill=tk.Y, padx=6)
        
        # -------- 价格配置框架内容 --------
        ttk.Label(config_frame, text="水费单价(元/吨):").grid(row=0, column=0, padx=4, pady=8, sticky=tk.W)
        self.water_price_entry = ttk.Entry(config_frame, width=10)
        self.water_price_entry.grid(row=0, column=1, padx=4, pady=8)
        
        ttk.Label(config_frame, text="电费单价(元/度):").grid(row=1, column=0, padx=4, pady=8, sticky=tk.W)
        self.electricity_price_entry = ttk.Entry(config_frame, width=10)
        self.electricity_price_entry.grid(row=1, column=1, padx=4, pady=8)
        
        # 收费标准列表区域 - 放置在右侧，占用剩余空间
        price_list_frame = ttk.LabelFrame(all_sections_frame, text="收费标准列表", padding=8, style='Card.TFrame')
        price_list_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(6, 0))
        
        # ========= 操作按钮区域 =========
        button_frame = ttk.Frame(price_content_frame)
        button_frame.pack(fill=tk.X, pady=10)
        
        # 左侧占位框架，帮助按钮居中
        left_spacer = ttk.Frame(button_frame)
        left_spacer.pack(side=tk.LEFT, expand=True)
        
        # 统一宽度的操作按钮
        ttk.Button(button_frame, text="保存收费标准", command=self.save_prices, width=12, style='Primary.TButton').pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="刷新类型列表", command=self.load_price_types, width=12).pack(side=tk.LEFT, padx=5)
        
        # 右侧占位框架
        right_spacer = ttk.Frame(button_frame)
        right_spacer.pack(side=tk.LEFT, expand=True)
        
        # 创建收费标准列表表格，优化高度和列宽以适应新布局
        columns = ("property_type", "water_price", "electricity_price")
        self.price_tree = ttk.Treeview(price_list_frame, columns=columns, show="headings", height=4)
        
        # 设置列标题和宽度，根据模块大小调整列宽
        self.price_tree.heading("property_type", text="物业类型")
        self.price_tree.heading("water_price", text="水费单价")
        self.price_tree.heading("electricity_price", text="电费单价")
        
        # 调整列宽以适应缩小后的列表框架
        self.price_tree.column("property_type", width=65, anchor=tk.CENTER)
        self.price_tree.column("water_price", width=60, anchor=tk.CENTER)
        self.price_tree.column("electricity_price", width=60, anchor=tk.CENTER)
        
        # 添加滚动条，确保表格能够正确显示
        scrollbar = ttk.Scrollbar(price_list_frame, orient=tk.VERTICAL, command=self.price_tree.yview)
        self.price_tree.configure(yscrollcommand=scrollbar.set)
        
        self.price_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 绑定选择事件
        self.price_tree.bind("<<TreeviewSelect>>", self.on_price_list_select)
        
        # 创建水平框架来容纳用户管理、备份恢复和软件信息框架
        management_frame = ttk.Frame(self.price_frame)
        management_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 用户管理框架 - 放置在左侧，高度设置为适中大小
        user_frame = ttk.LabelFrame(management_frame, text="用户管理", padding=15, height=100, style='Card.TFrame')
        user_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))
        user_frame.pack_propagate(False)
        
        # 复制setup_user_management_frame方法中的内容，但使用user_frame作为父框架
        # 按钮区域
        user_button_frame = ttk.Frame(user_frame)
        user_button_frame.pack(fill=tk.X, pady=10)
        
        # 添加按钮
        ttk.Button(user_button_frame, text="新增用户", command=self.add_user).pack(side=tk.LEFT, padx=5)
        ttk.Button(user_button_frame, text="编辑用户", command=self.edit_user).pack(side=tk.LEFT, padx=5)
        ttk.Button(user_button_frame, text="删除用户", command=self.delete_user).pack(side=tk.LEFT, padx=5)
        
        # 用户列表表格
        table_frame = ttk.Frame(user_frame)
        table_frame.pack(fill=tk.BOTH, expand=False)

        # 定义列
        columns = ("ID", "用户名", "角色")
        self.user_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=4)
        
        # 设置列标题和宽度
        for col in columns:
            self.user_tree.heading(col, text=col)
            if col == "ID":
                self.user_tree.column(col, width=50, anchor=tk.CENTER)
            elif col == "用户名":
                self.user_tree.column(col, width=150, anchor=tk.CENTER)
            else:
                self.user_tree.column(col, width=100, anchor=tk.CENTER)
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.user_tree.yview)
        self.user_tree.configure(yscrollcommand=scrollbar.set)
        
        self.user_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 备份恢复框架 - 放置在中间，高度与用户管理框架保持一致
        backup_frame = ttk.LabelFrame(management_frame, text="备份恢复", padding=15, height=20, style='Card.TFrame')
        backup_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5)
        backup_frame.pack_propagate(False)
        
        backup_button_frame = ttk.Frame(backup_frame)
        backup_button_frame.pack(pady=10)
        
        ttk.Button(backup_button_frame, text="数据备份", command=self.backup_database).pack(side=tk.LEFT, padx=10)
        ttk.Button(backup_button_frame, text="数据恢复", command=self.restore_database).pack(side=tk.LEFT, padx=10)
        ttk.Button(backup_button_frame, text="数据初始化", command=self.initialize_data).pack(side=tk.LEFT, padx=10)
        
        # 软件信息框架 - 放置在右侧，高度与其他框架保持一致
        software_info_frame = ttk.LabelFrame(management_frame, text="软件信息", padding=15, height=20, style='Card.TFrame')
        software_info_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(5, 0))
        software_info_frame.pack_propagate(False)
        
        # 创建软件信息内容框架
        info_content_frame = ttk.Frame(software_info_frame)
        info_content_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        # 添加软件信息字段，使用grid布局确保对齐
        # 第一行 - 软件品牌
        ttk.Label(info_content_frame, text="软件品牌:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
        self.software_brand_entry = ttk.Entry(info_content_frame, width=20)
        self.software_brand_entry.grid(row=0, column=1, sticky=tk.W, padx=5, pady=5)
        
        # 第二行 - 软件名称
        ttk.Label(info_content_frame, text="软件名称:").grid(row=1, column=0, sticky=tk.W, padx=5, pady=5)
        self.software_name_entry = ttk.Entry(info_content_frame, width=20)
        self.software_name_entry.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
        
        # 第三行 - 软件版本
        ttk.Label(info_content_frame, text="软件版本:").grid(row=2, column=0, sticky=tk.W, padx=5, pady=5)
        self.software_version_entry = ttk.Entry(info_content_frame, width=20)
        self.software_version_entry.grid(row=2, column=1, sticky=tk.W, padx=5, pady=5)
        
        # 第四行 - 设计人
        ttk.Label(info_content_frame, text="设计人:").grid(row=3, column=0, sticky=tk.W, padx=5, pady=5)
        self.software_designer_entry = ttk.Entry(info_content_frame, width=20)
        self.software_designer_entry.grid(row=3, column=1, sticky=tk.W, padx=5, pady=5)
        
        # 第五行 - E_mail
        ttk.Label(info_content_frame, text="E_mail:").grid(row=4, column=0, sticky=tk.W, padx=5, pady=5)
        self.software_email_entry = ttk.Entry(info_content_frame, width=20)
        self.software_email_entry.grid(row=4, column=1, sticky=tk.W, padx=5, pady=5)
        
        # 第六行 - 开发时间
        ttk.Label(info_content_frame, text="开发时间:").grid(row=5, column=0, sticky=tk.W, padx=5, pady=5)
        self.software_dev_time_entry = ttk.Entry(info_content_frame, width=20)
        self.software_dev_time_entry.grid(row=5, column=1, sticky=tk.W, padx=5, pady=5)
        
        # 保存按钮区域
        save_info_frame = ttk.Frame(software_info_frame)
        save_info_frame.pack(fill=tk.X, pady=10)
        
        ttk.Button(save_info_frame, text="保存软件信息", command=self.save_software_info, style='Primary.TButton').pack(side=tk.RIGHT, padx=5)
        
        # 加载软件信息
        self.load_software_info()
    
    def save_software_info(self):
        """
        保存软件信息到数据库
        用于将用户输入的软件信息保存到数据库中，支持全局调用
        """
        try:
            # 获取用户输入的软件信息
            brand = self.software_brand_entry.get().strip()
            name = self.software_name_entry.get().strip()
            version = self.software_version_entry.get().strip()
            designer = self.software_designer_entry.get().strip()
            email = self.software_email_entry.get().strip()
            dev_time = self.software_dev_time_entry.get().strip()
            
            # 连接数据库
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 确保软件信息表存在
            cursor.execute('''
            CREATE TABLE IF NOT EXISTS software_info (
                id INTEGER PRIMARY KEY,
                brand TEXT,
                name TEXT,
                version TEXT,
                designer TEXT,
                email TEXT,
                dev_time TEXT,
                update_time TEXT
            )
            ''')
            
            # 检查是否已有软件信息记录
            cursor.execute("SELECT id FROM software_info WHERE id = 1")
            existing_record = cursor.fetchone()
            
            # 获取当前时间作为更新时间
            update_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            if existing_record:
                # 更新现有记录
                cursor.execute('''
                UPDATE software_info 
                SET brand = ?, name = ?, version = ?, designer = ?, email = ?, dev_time = ?, update_time = ?
                WHERE id = 1
                ''', (brand, name, version, designer, email, dev_time, update_time))
            else:
                # 插入新记录
                cursor.execute('''
                INSERT INTO software_info (id, brand, name, version, designer, email, dev_time, update_time)
                VALUES (1, ?, ?, ?, ?, ?, ?, ?)
                ''', (brand, name, version, designer, email, dev_time, update_time))
            
            # 提交事务
            conn.commit()
            conn.close()
            
            # 显示成功消息
            messagebox.showinfo("成功", "软件信息已成功保存！")
            
        except Exception as e:
            print(f"保存软件信息时发生错误: {str(e)}")
            messagebox.showerror("错误", f"保存软件信息失败: {str(e)}")
    
    def get_software_info(self):
        """
        获取软件信息 - 全局调用方法
        返回软件信息的字典，供系统其他部分使用
        
        Returns:
            dict: 包含软件信息的字典，格式为 {
                'brand': 软件品牌,
                'name': 软件名称,
                'version': 软件版本,
                'designer': 设计人,
                'email': E_mail,
                'dev_time': 开发时间
            }
        """
        try:
            # 连接数据库
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 查询软件信息
            cursor.execute("SELECT brand, name, version, designer, email, dev_time FROM software_info WHERE id = 1")
            software_info = cursor.fetchone()
            
            # 关闭数据库连接
            conn.close()
            
            if software_info:
                return {
                    'brand': software_info[0] or "",
                    'name': software_info[1] or "",
                    'version': software_info[2] or "",
                    'designer': software_info[3] or "",
                    'email': software_info[4] or "",
                    'dev_time': software_info[5] or ""
                }
            else:
                # 返回默认空值
                return {
                    'brand': "",
                    'name': "",
                    'version': "",
                    'designer': "",
                    'email': "",
                    'dev_time': ""
                }
        except Exception as e:
            print(f"获取软件信息时发生错误: {str(e)}")
            # 发生错误时返回默认空值
            return {
                'brand': "",
                'name': "",
                'version': "",
                'designer': "",
                'email': "",
                'dev_time': ""
            }
    
    def load_software_info(self):
        """
        从数据库加载软件信息
        用于在页面加载时显示已保存的软件信息
        """
        try:
            # 连接数据库
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 查询软件信息表是否存在
            cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='software_info'")
            table_exists = cursor.fetchone()
            
            if table_exists:
                # 查询软件信息
                cursor.execute("SELECT brand, name, version, designer, email, dev_time FROM software_info WHERE id = 1")
                software_info = cursor.fetchone()
                
                if software_info:
                    # 填充表单
                    self.software_brand_entry.delete(0, tk.END)
                    self.software_brand_entry.insert(0, software_info[0] or "")
                    
                    self.software_name_entry.delete(0, tk.END)
                    self.software_name_entry.insert(0, software_info[1] or "")
                    
                    self.software_version_entry.delete(0, tk.END)
                    self.software_version_entry.insert(0, software_info[2] or "")
                    
                    self.software_designer_entry.delete(0, tk.END)
                    self.software_designer_entry.insert(0, software_info[3] or "")
                    
                    self.software_email_entry.delete(0, tk.END)
                    self.software_email_entry.insert(0, software_info[4] or "")
                    
                    self.software_dev_time_entry.delete(0, tk.END)
                    self.software_dev_time_entry.insert(0, software_info[5] or "")
            
            # 关闭数据库连接
            conn.close()
            
        except Exception as e:
            print(f"加载软件信息时发生错误: {str(e)}")
            # 加载失败时不显示错误消息，保持表单为空
            pass
        
        # 绑定选择事件
        self.price_type_combo.bind("<<ComboboxSelected>>", self.on_price_type_selected)
        
        # 加载价格类型和默认价格
        self.load_price_types()
        
        # 加载用户列表
        self.load_users()
        
        # 标记页面已加载
        self.price_tab_loaded = True
    
    def setup_property_tab(self):
        """基础信息管理页面"""
        property_frame = ttk.Frame(self.notebook)
        self.notebook.add(property_frame, text="基础信息")
        
        # 输入区域 - 使用卡片样式美化
        input_frame = ttk.LabelFrame(property_frame, text="物业信息录入", padding=10, style='Card.TFrame')
        input_frame.pack(fill=tk.X, padx=10, pady=10)
        
        # 创建水平排列的框架
        horizontal_input_frame = ttk.Frame(input_frame)
        horizontal_input_frame.pack(fill=tk.X, pady=5)
        
        # 名称字段 - 增加间距，使界面更宽松
        name_label = ttk.Label(horizontal_input_frame, text="名称:")
        name_label.pack(side=tk.LEFT, padx=(0, 5), pady=8)
        self.name_entry = ttk.Entry(horizontal_input_frame, width=20)
        self.name_entry.pack(side=tk.LEFT, padx=(0, 15), pady=8)
        
        # 类型字段 - 增加间距，使界面更宽松
        type_label = ttk.Label(horizontal_input_frame, text="类型:")
        type_label.pack(side=tk.LEFT, padx=(0, 5), pady=8)
        self.type_combo = ttk.Combobox(horizontal_input_frame, width=15)
        self.type_combo.pack(side=tk.LEFT, padx=(0, 15), pady=8)
        
        # 面积字段 - 增加间距，使界面更宽松
        area_label = ttk.Label(horizontal_input_frame, text="面积(㎡):")
        area_label.pack(side=tk.LEFT, padx=(0, 5), pady=8)
        self.area_entry = ttk.Entry(horizontal_input_frame, width=15)
        self.area_entry.pack(side=tk.LEFT, padx=(0, 15), pady=8)
        
        # 联系人字段 - 增加间距，使界面更宽松
        contact_label = ttk.Label(horizontal_input_frame, text="联系人:")
        contact_label.pack(side=tk.LEFT, padx=(0, 5), pady=8)
        self.contact_entry = ttk.Entry(horizontal_input_frame, width=15)
        self.contact_entry.pack(side=tk.LEFT, padx=(0, 15), pady=8)
        
        # 联系电话字段 - 增加间距，使界面更宽松
        phone_label = ttk.Label(horizontal_input_frame, text="联系电话:")
        phone_label.pack(side=tk.LEFT, padx=(0, 5), pady=8)
        self.phone_entry = ttk.Entry(horizontal_input_frame, width=20)
        self.phone_entry.pack(side=tk.LEFT, padx=(0, 15), pady=8)
        
        # 按钮区域 - 优化间距
        button_frame = ttk.Frame(input_frame)
        button_frame.pack(fill=tk.X, pady=15)
        
        # 添加一个占位框架，帮助按钮居中
        left_spacer = ttk.Frame(button_frame)
        left_spacer.pack(side=tk.LEFT, expand=True)
        
        # 重要操作使用主按钮样式
        ttk.Button(button_frame, text="新增", command=self.add_property, style='Primary.TButton').pack(side=tk.LEFT, padx=10, pady=5)
        ttk.Button(button_frame, text="修改", command=self.update_property, style='Primary.TButton').pack(side=tk.LEFT, padx=10, pady=5)
        ttk.Button(button_frame, text="删除", command=self.delete_property).pack(side=tk.LEFT, padx=10, pady=5)
        ttk.Button(button_frame, text="清空", command=self.clear_property_form).pack(side=tk.LEFT, padx=10, pady=5)
        ttk.Button(button_frame, text="导出物业资料", command=self.export_property_data).pack(side=tk.LEFT, padx=10, pady=5)
        ttk.Button(button_frame, text="导入物业资料", command=self.import_property_data).pack(side=tk.LEFT, padx=10, pady=5)
        
        # 右侧占位框架
        right_spacer = ttk.Frame(button_frame)
        right_spacer.pack(side=tk.LEFT, expand=True)
        
        # 加载所有可用的物业类型
        self.load_property_types()
        
        # 数据表格 - 使用卡片样式美化
        table_frame = ttk.LabelFrame(property_frame, text="物业列表", padding=10, style='Card.TFrame')
        table_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        columns = ("序号", "ID", "名称", "类型", "面积", "联系人", "联系电话", "状态")
        self.property_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=15)
        
        for col in columns:
            self.property_tree.heading(col, text=col)
            if col == "ID":
                # 完全隐藏ID列
                self.property_tree.column(col, width=0, minwidth=0, stretch=0)
            else:
                self.property_tree.column(col, width=100)
        
        scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.property_tree.yview)
        self.property_tree.configure(yscrollcommand=scrollbar.set)
        
        self.property_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 绑定点击事件
        self.property_tree.bind("<<TreeviewSelect>>", self.on_property_select)
        
        # 加载数据
        self.load_properties()
    
    def setup_price_tab(self):
        """收费标准配置页面"""
        # 创建一个框架
        self.price_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.price_frame, text="系统设置")
        
        # 简化实现：只显示一个基本的提示信息，避免复杂加载逻辑影响其他页面
        ttk.Label(self.price_frame, text="系统设置页面", font=('微软雅黑', 14)).pack(pady=20)
        ttk.Label(self.price_frame, text="点击“进入设置”按钮加载完整内容", font=('微软雅黑', 10)).pack(pady=10)
        refresh_button = ttk.Button(self.price_frame, text="进入设置", command=self.refresh_price_tab, style='Primary.TButton')
        refresh_button.pack(pady=20)
        
        # 初始化相关属性
        self.price_tab_loaded = False
        
    def refresh_price_tab(self):
        """刷新系统设置页面内容"""
        # 在进入设置前进行密码验证
        if not self.verify_password("刷新系统设置页面"):
            messagebox.showinfo("操作取消", "密码验证失败，无法进入设置")
            return
            
        try:
            # 清空框架
            for widget in self.price_frame.winfo_children():
                widget.destroy()
            
            # 加载页面内容
            self.load_price_tab_content()
            self.price_tab_loaded = True
        except Exception as e:
            print(f"刷新系统设置页面内容时发生错误: {str(e)}")
            error_label = ttk.Label(self.price_frame, text=f"进入设置失败: {str(e)}", 
                                   font=('微软雅黑', 12), foreground='#e74c3c')
            error_label.pack(pady=50)
    
    def setup_reading_tab(self):
        """抄表计算页面"""
        reading_frame = ttk.Frame(self.notebook)
        self.notebook.add(reading_frame, text="水电抄表")
        
        # 选择物业和日期
        selection_frame = ttk.LabelFrame(reading_frame, text="选择条件", padding=10)
        selection_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(selection_frame, text="选择物业:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        self.reading_property_combo = ttk.Combobox(selection_frame, width=20, state="readonly")
        self.reading_property_combo.grid(row=0, column=1, padx=5, pady=5)
        # 添加物业类型标签
        self.property_type_label = ttk.Label(selection_frame, text="(物业类型)", foreground="gray")
        self.property_type_label.grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)
        # 绑定物业选择变化事件
        self.reading_property_combo.bind("<<ComboboxSelected>>", self.on_property_selected)
        
        ttk.Label(selection_frame, text="抄表月份:").grid(row=0, column=3, padx=5, pady=5, sticky=tk.W)
        self.reading_month_combo = ttk.Combobox(selection_frame, width=15, state="normal")
        self.reading_month_combo.grid(row=0, column=4, padx=5, pady=5)
        

        ttk.Button(selection_frame, text="加载历史记录", command=self.load_reading_history).grid(row=0, column=5, padx=5, pady=5)
        ttk.Button(selection_frame, text="生成抄表单", command=self.generate_reading_form).grid(row=0, column=6, padx=5, pady=5)
        ttk.Button(selection_frame, text="导入抄表数据", command=self.import_reading_data).grid(row=0, column=7, padx=5, pady=5)
        ttk.Button(selection_frame, text="本月总水表抄数", command=self.show_total_water_meter).grid(row=0, column=8, padx=5, pady=5)
        
        # 抄表数据输入
        data_frame = ttk.LabelFrame(reading_frame, text="抄表数据录入", padding=10)
        data_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 水表和电表数据在同一行显示
        ttk.Label(data_frame, text="水表上月读数:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        self.water_previous = ttk.Entry(data_frame, width=15)
        self.water_previous.grid(row=0, column=1, padx=5, pady=5)
        
        ttk.Label(data_frame, text="水表本月读数:").grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)
        self.water_current = ttk.Entry(data_frame, width=15)
        self.water_current.grid(row=0, column=3, padx=5, pady=5)
        
        ttk.Label(data_frame, text="水表调整量:").grid(row=0, column=4, padx=5, pady=5, sticky=tk.W)
        self.water_adjustment = ttk.Entry(data_frame, width=15)
        self.water_adjustment.grid(row=0, column=5, padx=5, pady=5)
        self.water_adjustment.insert(0, "0")
        
        # 添加分隔符
        ttk.Label(data_frame, text="|").grid(row=0, column=6, padx=5, pady=5)
        
        # 电表数据移至水表调整量后方
        ttk.Label(data_frame, text="电表上月读数:").grid(row=0, column=7, padx=5, pady=5, sticky=tk.W)
        self.electricity_previous = ttk.Entry(data_frame, width=15)
        self.electricity_previous.grid(row=0, column=8, padx=5, pady=5)
        
        ttk.Label(data_frame, text="电表本月读数:").grid(row=0, column=9, padx=5, pady=5, sticky=tk.W)
        self.electricity_current = ttk.Entry(data_frame, width=15)
        self.electricity_current.grid(row=0, column=10, padx=5, pady=5)
        
        ttk.Label(data_frame, text="电表调整量:").grid(row=0, column=11, padx=5, pady=5, sticky=tk.W)
        self.electricity_adjustment = ttk.Entry(data_frame, width=15)
        self.electricity_adjustment.grid(row=0, column=12, padx=5, pady=5)
        self.electricity_adjustment.insert(0, "0")
        
        # 计算结果
        result_frame = ttk.LabelFrame(reading_frame, text="计算结果", padding=10)
        result_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(result_frame, text="水费金额:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        self.water_amount_label = ttk.Label(result_frame, text="0元", foreground="blue")
        self.water_amount_label.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)
        
        ttk.Label(result_frame, text="电费金额:").grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)
        self.electricity_amount_label = ttk.Label(result_frame, text="0元", foreground="blue")
        self.electricity_amount_label.grid(row=0, column=3, padx=5, pady=5, sticky=tk.W)
        
        ttk.Label(result_frame, text="总金额:").grid(row=0, column=4, padx=5, pady=5, sticky=tk.W)
        # 使用StringVar来管理总金额标签的值，以确保正确更新
        self.total_amount_var = tk.StringVar(value="0元")
        self.total_amount_label = ttk.Label(result_frame, textvariable=self.total_amount_var, foreground="red", font=('微软雅黑', 12, 'bold'))
        self.total_amount_label.grid(row=0, column=5, padx=5, pady=5, sticky=tk.W)
        
        # 按钮区域 - 使用卡片样式增加层次感
        button_frame = ttk.Frame(reading_frame, style='Card.TFrame')
        button_frame.pack(fill=tk.X, pady=10, padx=5)
        
        # 左侧按钮组
        left_buttons = ttk.Frame(button_frame)
        left_buttons.pack(side=tk.LEFT, padx=10, pady=8)
        
        # 重要操作使用主按钮样式
        ttk.Button(left_buttons, text="计算费用", command=self.calculate_amount, style='Primary.TButton').pack(side=tk.LEFT, padx=5)
        ttk.Button(left_buttons, text="保存记录", command=self.save_reading, style='Primary.TButton').pack(side=tk.LEFT, padx=5)
        
        # 普通操作使用默认按钮样式
        ttk.Button(left_buttons, text="清空表单", command=self.clear_reading_form).pack(side=tk.LEFT, padx=5)
        ttk.Button(left_buttons, text="删除记录", command=self.delete_reading_record, width=10).pack(side=tk.LEFT, padx=5)
        ttk.Button(left_buttons, text="刷新列表", command=self.load_reading_history, width=10).pack(side=tk.LEFT, padx=5)
        ttk.Button(left_buttons, text="生成账单", command=self.generate_bill, width=10).pack(side=tk.LEFT, padx=5)
        ttk.Button(left_buttons, text="导出Excel", command=self.export_to_excel, width=10).pack(side=tk.LEFT, padx=5)
        
        # 添加统计标签组
        stats_frame = ttk.Frame(button_frame)
        stats_frame.pack(side=tk.LEFT, padx=20)
        
        # 设置统计标签样式为绿色常规字体
        stats_style = {'foreground': 'green'}
        
        # 添加统计标签
        self.records_count_label = ttk.Label(stats_frame, text="记录条数: 0", **stats_style)
        self.records_count_label.pack(side=tk.LEFT, padx=10)
        
        self.water_total_label = ttk.Label(stats_frame, text="水费金额: 0.00元", **stats_style)
        self.water_total_label.pack(side=tk.LEFT, padx=10)
        
        self.electricity_total_label = ttk.Label(stats_frame, text="电费金额: 0.00元", **stats_style)
        self.electricity_total_label.pack(side=tk.LEFT, padx=10)
        
        self.total_amount_total_label = ttk.Label(stats_frame, text="总金额: 0.00元", **stats_style)
        self.total_amount_total_label.pack(side=tk.LEFT, padx=10)
        
        self.water_usage_label = ttk.Label(stats_frame, text="水用量: 0吨", **stats_style)
        self.water_usage_label.pack(side=tk.LEFT, padx=10)
        
        self.electricity_usage_label = ttk.Label(stats_frame, text="电用量: 0度", **stats_style)
        self.electricity_usage_label.pack(side=tk.LEFT, padx=10)
        
        # 新增：抄表明细列表
        details_frame = ttk.LabelFrame(reading_frame, text="抄表明细记录", padding=10)
        details_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建表格
        columns = ("ID", "序号", "物业名称", "月份", "水表读数", "水表调整量", "水用量\吨", "水费\元", "电表读数", "电表调整量", "电用量\度", "电费\元", "总金额\元", "状态")
        self.reading_details_tree = ttk.Treeview(details_frame, columns=columns, show="headings", height=8)
        
        # 设置列宽
        column_widths = {
            "序号": 60, "物业名称": 150, "月份": 100, "水表读数": 120, "水表调整量": 90, "水用量": 80, "水费": 80,
            "电表读数": 120, "电表调整量": 90, "电用量": 80, "电费": 80, "总金额": 90, "状态": 80
        }
        
        for col in columns:
            self.reading_details_tree.heading(col, text=col)
            if col == "ID":
                # 完全隐藏ID列
                self.reading_details_tree.column(col, width=0, minwidth=0, stretch=0)
            else:
                self.reading_details_tree.column(col, width=column_widths.get(col, 100))
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(details_frame, orient=tk.VERTICAL, command=self.reading_details_tree.yview)
        self.reading_details_tree.configure(yscrollcommand=scrollbar.set)
        
        self.reading_details_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 明细列表操作按钮
        # 移除编辑选中记录按钮，其他操作按钮已移至上方主按钮区域
        # 保留右侧空白区域以保持界面平衡
        details_button_frame = ttk.Frame(details_frame)
        details_button_frame.pack(fill=tk.Y, side=tk.RIGHT, pady=5)
        
        # 绑定点击事件
        self.reading_details_tree.bind("<<TreeviewSelect>>", self.on_reading_record_select)
        
        # 初始化下拉框
        self.update_reading_combos()
        
        # 页面加载时不显示所有记录，只在选择物业和月份后显示
        # 清空表格
        for item in self.reading_details_tree.get_children():
            self.reading_details_tree.delete(item)
    
    def setup_report_tab(self):
        """报表生成页面"""
        report_frame = ttk.Frame(self.notebook)
        self.notebook.add(report_frame, text="查询报表")
        
        # 查询条件 - 使用卡片样式美化
        query_frame = ttk.LabelFrame(report_frame, text="查询条件", padding=10, style='Card.TFrame')
        query_frame.pack(fill=tk.X, padx=10, pady=10)
        
        # 左侧查询条件（增加间距，使界面更宽松）
        ttk.Label(query_frame, text="选择月份:").grid(row=0, column=0, padx=10, pady=10, sticky=tk.W)
        self.report_month_combo = ttk.Combobox(query_frame, width=15, state="readonly")
        self.report_month_combo.grid(row=0, column=1, padx=5, pady=10)
        
        ttk.Label(query_frame, text="物业类型:").grid(row=0, column=2, padx=10, pady=10, sticky=tk.W)
        self.report_type_combo = ttk.Combobox(query_frame, width=15, state="readonly")
        self.report_type_combo.grid(row=0, column=3, padx=5, pady=10)
        
        ttk.Label(query_frame, text="物业名称:").grid(row=0, column=4, padx=10, pady=10, sticky=tk.W)
        self.report_property_combo = ttk.Combobox(query_frame, width=20, state="readonly")
        self.report_property_combo.grid(row=0, column=5, padx=5, pady=10)
        
        # 按钮美化 - 重要操作使用主按钮样式
        ttk.Button(query_frame, text="查询", command=self.generate_report, style='Primary.TButton').grid(row=0, column=6, padx=10, pady=10)
        ttk.Button(query_frame, text="导出Excel", command=self.export_excel).grid(row=0, column=7, padx=5, pady=10)
        ttk.Button(query_frame, text="报表分析", command=self.analyze_report).grid(row=0, column=8, padx=5, pady=10)
        
        # 记录总条数和金额总和显示标签
        self.summary_label = ttk.Label(query_frame, text="总计: 0条记录, 水费: 0.00元  电费: 0.00元  总金额: 0.00元", font= ("SimHei", 10), foreground="green")
        self.summary_label.grid(row=0, column=9, padx=15, pady=5, sticky=tk.W)
        
        # 报表表格 - 使用卡片样式美化
        table_frame = ttk.LabelFrame(report_frame, text="水电费报表", padding=10, style='Card.TFrame')
        table_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        columns = ("序号", "状态", "物业名称", "类型", "月份", "水表读数", "水用量", "水表调整量", "水费", "电表读数", "电用量", "电表调整量", "电费", "总金额", "抄表日期")
        self.report_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=15)
        
        # 设置列标题和宽度
        for col in columns:
            self.report_tree.heading(col, text=col)
            # 为序号列设置较小的宽度
            if col == "序号":
                self.report_tree.column(col, width=60, anchor=tk.CENTER)
            # 为状态列设置较小的宽度
            elif col == "状态":
                self.report_tree.column(col, width=80, anchor=tk.CENTER)
            else:
                self.report_tree.column(col, width=120, anchor=tk.CENTER)
                
        # 添加标签样式，用于区分状态
        self.report_tree.tag_configure('paid', foreground='green')
        self.report_tree.tag_configure('unpaid', foreground='red')
        
        scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.report_tree.yview)
        self.report_tree.configure(yscrollcommand=scrollbar.set)
        
        self.report_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        

        

        # 初始化月份下拉框
        self.update_report_month_combo()
        
        # 加载物业类型
        self.load_report_property_types()
        # 加载物业名称
        self.load_report_properties()
        

    def load_users(self):
        """加载所有用户信息到用户列表"""
        # 清空现有数据
        for item in self.user_tree.get_children():
            self.user_tree.delete(item)
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            cursor.execute("SELECT id, username, role FROM users ORDER BY username ASC")
            users = cursor.fetchall()
            conn.close()
            
            # 将用户信息添加到列表
            for user in users:
                self.user_tree.insert('', tk.END, values=user)
        except Exception as e:
            messagebox.showerror("错误", f"加载用户信息失败: {str(e)}")
    
    def add_user(self):
        """新增用户功能"""
        # 创建新增用户对话框
        dialog = tk.Toplevel(self.root)
        dialog.title("新增用户")
        dialog.geometry("400x300")
        dialog.resizable(False, False)
        dialog.transient(self.root)  # 设置为主窗口的子窗口
        dialog.grab_set()  # 模态窗口
        
        # 居中显示
        dialog.update_idletasks()
        width = dialog.winfo_width()
        height = dialog.winfo_height()
        x = (dialog.winfo_screenwidth() // 2) - (width // 2)
        y = (dialog.winfo_screenheight() // 2) - (height // 2)
        dialog.geometry(f"{width}x{height}+{x}+{y}")
        
        # 主框架
        main_frame = ttk.Frame(dialog, padding=30)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title_label = ttk.Label(main_frame, text="新增用户", font=('微软雅黑', 14, 'bold'))
        title_label.pack(pady=(0, 20))
        
        # 用户名
        username_frame = ttk.Frame(main_frame)
        username_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(username_frame, text="用户名：").pack(side=tk.LEFT, padx=(0, 10))
        username_entry = ttk.Entry(username_frame, font=('微软雅黑', 10), width=20)
        username_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 密码
        password_frame = ttk.Frame(main_frame)
        password_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(password_frame, text="密码：").pack(side=tk.LEFT, padx=(0, 10))
        password_entry = ttk.Entry(password_frame, font=('微软雅黑', 10), width=20, show="*")
        password_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 确认密码
        confirm_frame = ttk.Frame(main_frame)
        confirm_frame.pack(fill=tk.X, pady=(0, 20))
        
        ttk.Label(confirm_frame, text="确认密码：").pack(side=tk.LEFT, padx=(0, 10))
        confirm_entry = ttk.Entry(confirm_frame, font=('微软雅黑', 10), width=20, show="*")
        confirm_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=(0, 10))
        
        def save_new_user():
            username = username_entry.get().strip()
            password = password_entry.get().strip()
            confirm_password = confirm_entry.get().strip()
            
            # 验证输入
            if not username or not password:
                messagebox.showerror("错误", "用户名和密码不能为空！")
                return
            
            if password != confirm_password:
                messagebox.showerror("错误", "两次输入的密码不一致！")
                return
            
            # 保存新用户
            try:
                conn = sqlite3.connect('water_electricity.db')
                cursor = conn.cursor()
                
                # 检查用户是否已存在
                cursor.execute("SELECT id FROM users WHERE username=?", (username,))
                if cursor.fetchone():
                    messagebox.showerror("错误", "用户名已存在！")
                    conn.close()
                    return
                
                # 插入新用户
                cursor.execute(
                    "INSERT INTO users (username, password, role) VALUES (?, ?, ?)",
                    (username, password, 'user')
                )
                
                conn.commit()
                conn.close()
                
                messagebox.showinfo("成功", "用户创建成功！")
                dialog.destroy()
                # 刷新用户列表
                self.load_users()
            except Exception as e:
                messagebox.showerror("错误", f"创建用户失败: {str(e)}")
        
        ttk.Button(button_frame, text="保存", command=save_new_user).pack(side=tk.LEFT, padx=(0, 10), fill=tk.X, expand=True)
        ttk.Button(button_frame, text="取消", command=dialog.destroy).pack(side=tk.LEFT, fill=tk.X, expand=True)
    
    def edit_user(self):
        """编辑用户功能"""
        # 获取选中的用户
        selected_items = self.user_tree.selection()
        if not selected_items:
            messagebox.showinfo("提示", "请先选择要编辑的用户")
            return
        
        selected_item = selected_items[0]
        user_data = self.user_tree.item(selected_item, "values")
        user_id = user_data[0]
        current_username = user_data[1]
        
        # 不能编辑admin用户
        if current_username == "admin":
            messagebox.showinfo("提示", "管理员用户不能被编辑")
            return
        
        # 创建编辑用户对话框
        dialog = tk.Toplevel(self.root)
        dialog.title("编辑用户")
        dialog.geometry("400x300")
        dialog.resizable(False, False)
        dialog.transient(self.root)  # 设置为主窗口的子窗口
        dialog.grab_set()  # 模态窗口
        
        # 居中显示
        dialog.update_idletasks()
        width = dialog.winfo_width()
        height = dialog.winfo_height()
        x = (dialog.winfo_screenwidth() // 2) - (width // 2)
        y = (dialog.winfo_screenheight() // 2) - (height // 2)
        dialog.geometry(f"{width}x{height}+{x}+{y}")
        
        # 主框架
        main_frame = ttk.Frame(dialog, padding=30)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title_label = ttk.Label(main_frame, text="编辑用户", font=('微软雅黑', 14, 'bold'))
        title_label.pack(pady=(0, 20))
        
        # 用户名（只读）
        username_frame = ttk.Frame(main_frame)
        username_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(username_frame, text="用户名：").pack(side=tk.LEFT, padx=(0, 10))
        username_entry = ttk.Entry(username_frame, font=('微软雅黑', 10), width=20)
        username_entry.insert(0, current_username)
        username_entry.config(state="readonly")
        username_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 新密码
        password_frame = ttk.Frame(main_frame)
        password_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(password_frame, text="新密码：").pack(side=tk.LEFT, padx=(0, 10))
        password_entry = ttk.Entry(password_frame, font=('微软雅黑', 10), width=20, show="*")
        password_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 确认新密码
        confirm_frame = ttk.Frame(main_frame)
        confirm_frame.pack(fill=tk.X, pady=(0, 20))
        
        ttk.Label(confirm_frame, text="确认新密码：").pack(side=tk.LEFT, padx=(0, 10))
        confirm_entry = ttk.Entry(confirm_frame, font=('微软雅黑', 10), width=20, show="*")
        confirm_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=(0, 10))
        
        def save_edited_user():
            new_password = password_entry.get().strip()
            confirm_password = confirm_entry.get().strip()
            
            # 验证输入
            if new_password and new_password != confirm_password:
                messagebox.showerror("错误", "两次输入的密码不一致！")
                return
            
            # 更新用户
            try:
                conn = sqlite3.connect('water_electricity.db')
                cursor = conn.cursor()
                
                if new_password:
                    # 更新密码
                    cursor.execute("UPDATE users SET password=? WHERE id=?", (new_password, user_id))
                    
                conn.commit()
                conn.close()
                
                messagebox.showinfo("成功", "用户更新成功！")
                dialog.destroy()
                # 刷新用户列表
                self.load_users()
            except Exception as e:
                messagebox.showerror("错误", f"更新用户失败: {str(e)}")
        
        ttk.Button(button_frame, text="保存", command=save_edited_user).pack(side=tk.LEFT, padx=(0, 10), fill=tk.X, expand=True)
        ttk.Button(button_frame, text="取消", command=dialog.destroy).pack(side=tk.LEFT, fill=tk.X, expand=True)
    
    def delete_user(self):
        """删除用户功能"""
        # 获取选中的用户
        selected_items = self.user_tree.selection()
        if not selected_items:
            messagebox.showinfo("提示", "请先选择要删除的用户")
            return
        
        selected_item = selected_items[0]
        user_data = self.user_tree.item(selected_item, "values")
        user_id = user_data[0]
        username = user_data[1]
        
        # 不能删除admin用户
        if username == "admin":
            messagebox.showinfo("提示", "管理员用户不能被删除")
            return
        
        # 确认删除
        if messagebox.askyesno("确认", f"确定要删除用户 '{username}' 吗？"):
            try:
                conn = sqlite3.connect('water_electricity.db')
                cursor = conn.cursor()
                
                # 删除用户
                cursor.execute("DELETE FROM users WHERE id=?", (user_id,))
                
                conn.commit()
                conn.close()
                
                messagebox.showinfo("成功", "用户删除成功！")
                # 刷新用户列表
                self.load_users()
            except Exception as e:
                messagebox.showerror("错误", f"删除用户失败: {str(e)}")
                
    def load_report_property_types(self):
        """加载物业类型到报表页面的下拉框"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT property_type FROM price_config ORDER BY property_type")
        types = [row[0] for row in cursor.fetchall()]
        conn.close()
        
        # 去重处理
        unique_types = list(dict.fromkeys(types))
        
        # 添加"全部"选项
        all_types = ["全部"] + unique_types
        
        self.report_type_combo['values'] = all_types
        if all_types:
            self.report_type_combo.current(0)  # 默认选择"全部"

    def setup_about_tab(self):
        """关于页面"""
        about_frame = ttk.Frame(self.notebook)
        self.notebook.add(about_frame, text="关于")
        
        # 创建主内容框架，居中显示
        content_frame = ttk.Frame(about_frame, padding=30)
        content_frame.pack(expand=True, fill=tk.BOTH)
        
        # 标题和版本信息
        # title_frame = ttk.Frame(content_frame)
        # title_frame.pack(pady=(0, 30))
        
        # ttk.Label(title_frame, text="《吾已水电费管理系统》", style='Header.TLabel').pack(side=tk.LEFT, padx=(0, 10)); ttk.Label(title_frame, text="版本 v1.5", font=('微软雅黑', 10)).pack(side=tk.LEFT, pady=(5, 0), fill=tk.Y, expand=True)
        
        # 项目概述 - 使用卡片样式美化
        overview_frame = ttk.LabelFrame(content_frame, text="项目概述", padding=20, style='Card.TFrame')
        overview_frame.pack(fill=tk.X, pady=(0, 20))
        
        # 从软件信息模块获取软件品牌和名称
        software_info = self.get_software_info()
        brand = software_info.get('brand', '')
        name = software_info.get('name', '水电费管理系统')
        # 构建软件名称文本，优先使用品牌+名称
        software_name = f"《{brand}{name}》" if brand else f"《{name}》"
        
        overview_text = f"""{software_name}是一款专为物业管理人员设计的水电费收取与统计软件，提供了物业基础信息管理、收费标准配置、抄表记录、费用计算、收款管理以及报表生成等全方位功能。系统采用直观的图形界面，操作简便，能够有效提高物业水电费管理的工作效率。"""
        # 创建标签并使用更新函数确保宽度正确设置
        overview_label = ttk.Label(overview_frame, text=overview_text, wraplength=1, justify=tk.LEFT, style='Feature.TLabel')
        overview_label.pack(fill=tk.BOTH)
        
        # 定义一个函数来设置基于框架宽度的换行宽度
        def update_wraplength(event=None):
            # 等待框架渲染完成后获取实际宽度
            frame_width = overview_frame.winfo_width()
            # 设置换行宽度为框架宽度的95%（留出一些边距）
            if frame_width > 10:  # 确保宽度有效
                overview_label.config(wraplength=int(frame_width * 0.95))
        
        # 绑定事件以响应框架大小变化
        overview_frame.bind('<Configure>', update_wraplength)
        # 初始调用一次以设置正确的宽度
        overview_frame.after(100, update_wraplength)
        
        # 主要功能亮点 - 使用卡片样式美化
        features_frame = ttk.LabelFrame(content_frame, text="主要功能", padding=20, style='Card.TFrame')
        features_frame.pack(fill=tk.X, pady=(0, 20))
        
        # 创建功能列表框架，使用网格布局
        features_grid_frame = ttk.Frame(features_frame)
        features_grid_frame.pack(fill=tk.BOTH, expand=True)
        
        # 主要功能列表
        features = [
            "完整的物业基础信息管理",
            "灵活的收费标准配置",
            "便捷的抄表数据录入与计算",
            "详细的收款记录跟踪",
            "多维度的报表统计与导出",
            "数据持久化存储"
        ]
        
        # 网格布局显示功能（每行显示2个项目，更适合大多数屏幕宽度）
        for i, feature in enumerate(features):
            row = i // 6
            col = i % 6
            ttk.Label(features_grid_frame, text="• " + feature, style='Feature.TLabel').grid(row=row, column=col, sticky=tk.W, padx=20, pady=10)
        
        # 系统架构 - 使用卡片样式美化
        architecture_frame = ttk.LabelFrame(content_frame, text="系统架构", padding=20, style='Card.TFrame')
        architecture_frame.pack(fill=tk.X, pady=(0, 20))
        
        # 从软件信息模块获取数据
        software_info = self.get_software_info()
        brand = software_info.get('brand', '')
        name = software_info.get('name', '吾已水电费管理系统')
        version = software_info.get('version', 'v1.5')
        designer = software_info.get('designer', '吾已（lymin_li）')
        email = software_info.get('email', 'lymin_li@qq.com')
        dev_time = software_info.get('dev_time', '')
        
        # 构建软件名称文本
        if brand:
            software_name = f"《{brand}{name}》"
        else:
            software_name = f"《{name}》"
        
        # 系统架构信息，使用文本框显示
        architecture_text = """
软件名称：{software_name}{version}
        开发者：{designer} E_mail:{email}
        """.format(software_name=software_name, version=version, designer=designer, email=email)
        
        # 如果有开发时间信息，添加到文本中
        if dev_time:
            architecture_text += "开发时间：{dev_time}\n        ".format(dev_time=dev_time)
        
        architecture_text += """
核心库与框架：
- Tkinter: 用于构建图形用户界面
- SQLite3: 轻量级数据库，用于数据存储
- Openpyxl: Excel文件处理，用于数据导出

系统结构：
- main.py: 程序入口，初始化数据库和UI
- ui_design.py: 用户界面设计和功能实现
- water_electricity.db: SQLite数据库文件
- Run.bat: 快捷启动脚本
- requirements.txt: 项目依赖声明"""
        
        text_widget = tk.Text(architecture_frame, wrap=tk.WORD, font=('微软雅黑', 10), height=10, width=80)
        text_widget.insert(tk.END, architecture_text)
        text_widget.config(state=tk.DISABLED)  # 设置为只读
        text_widget.pack(fill=tk.BOTH, expand=True)
        
        # 页脚信息
        footer_frame = ttk.Frame(content_frame)
        footer_frame.pack(fill=tk.X, pady=(20, 0))
        
        # 从软件信息模块获取数据
        software_info = self.get_software_info()
        brand = software_info.get('brand', '')
        name = software_info.get('name', '吾已水电费管理系统')
        
        # 构建软件名称文本
        if brand:
            software_name = f"《{brand}{name}》"
        else:
            software_name = f"《{name}》"
        
        # 创建版权信息标签
        ttk.Label(footer_frame, text=f"© 2025 {software_name} 版权所有", font=('微软雅黑', 10, 'italic')).pack(anchor=tk.CENTER)
            
    def load_report_properties(self):
        """加载物业名称到报表页面的下拉框"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT id, name FROM properties ORDER BY name")
        properties = [f"{row[0]}-{row[1]}" for row in cursor.fetchall()]
        conn.close()
        
        # 添加"全部"选项
        all_properties = ["全部"] + properties
        
        self.report_property_combo['values'] = all_properties
        if all_properties:
            self.report_property_combo.current(0)  # 默认选择"全部"
    
    def setup_payment_tab(self):
        """收款管理页面"""
        payment_frame = ttk.Frame(self.notebook)
        self.notebook.add(payment_frame, text="收款管理")
        
        # 账单列表 - 使用卡片样式美化
        bills_frame = ttk.LabelFrame(payment_frame, text="待收款账单", padding=10, style='Card.TFrame')
        bills_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        columns = ("ID", "序号", "物业名称", "账单月份", "总金额", "状态", "生成日期")
        self.bills_tree = ttk.Treeview(bills_frame, columns=columns, show="headings", height=10)
        
        for col in columns:
            self.bills_tree.heading(col, text=col)
            if col == "ID":
                # 完全隐藏ID列
                self.bills_tree.column(col, width=0, minwidth=0, stretch=0)
            else:
                self.bills_tree.column(col, width=100)
        
        scrollbar1 = ttk.Scrollbar(bills_frame, orient=tk.VERTICAL, command=self.bills_tree.yview)
        self.bills_tree.configure(yscrollcommand=scrollbar1.set)
        
        self.bills_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar1.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 添加选择事件绑定
        self.bills_tree.bind('<<TreeviewSelect>>', self.on_bill_select)
        
        # 创建一个容器框架来放置收款操作和收款记录筛选
        operations_container = ttk.Frame(payment_frame)
        operations_container.pack(fill=tk.X, padx=10, pady=5)
        
        # 收款操作 - 使用卡片样式美化
        payment_ops_frame = ttk.LabelFrame(operations_container, text="收款操作", padding=10, style='Card.TFrame')
        payment_ops_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5), pady=0)
        
        ttk.Label(payment_ops_frame, text="缴费人:").grid(row=0, column=0, padx=5, pady=10, sticky=tk.W)
        self.payer_entry = ttk.Entry(payment_ops_frame, width=20)
        self.payer_entry.grid(row=0, column=1, padx=5, pady=10)
        
        ttk.Label(payment_ops_frame, text="缴费日期:").grid(row=0, column=2, padx=5, pady=10, sticky=tk.W)
        self.payment_date_entry = ttk.Entry(payment_ops_frame, width=15)
        self.payment_date_entry.grid(row=0, column=3, padx=5, pady=10)
        self.payment_date_entry.insert(0, datetime.now().strftime("%Y-%m-%d"))
        
        ttk.Label(payment_ops_frame, text="备注:").grid(row=1, column=0, padx=5, pady=10, sticky=tk.W)
        self.payment_notes_entry = ttk.Entry(payment_ops_frame, width=50)
        self.payment_notes_entry.grid(row=1, column=1, columnspan=3, padx=5, pady=10, sticky=tk.W+tk.E)
        
        # 收款确认按钮使用主按钮样式突出显示
        ttk.Button(payment_ops_frame, text="收款确认", command=self.mark_paid, style='Primary.TButton').grid(row=0, column=4, padx=5, pady=10)
        ttk.Button(payment_ops_frame, text="删除待收款记录", command=self.cancel_bill).grid(row=0, column=5, padx=5, pady=10)
        ttk.Button(payment_ops_frame, text="刷新列表", command=self.load_bills).grid(row=1, column=4, padx=5, pady=10)
        ttk.Button(payment_ops_frame, text="删除收款记录", command=self.delete_payment_record).grid(row=1, column=5, padx=5, pady=10)
        
        # 收款记录筛选 - 使用卡片样式美化
        filter_frame = ttk.LabelFrame(operations_container, text="收款记录筛选", padding=10, style='Card.TFrame')
        filter_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(5, 0), pady=0)
        
        ttk.Label(filter_frame, text="账单月份:").grid(row=0, column=0, padx=5, pady=10, sticky=tk.W)
        self.payment_month_combo = ttk.Combobox(filter_frame, width=15, state="readonly")
        self.payment_month_combo.grid(row=0, column=1, padx=5, pady=10)
        
        ttk.Label(filter_frame, text="物业名称:").grid(row=0, column=2, padx=5, pady=10, sticky=tk.W)
        self.payment_property_combo = ttk.Combobox(filter_frame, width=20, state="readonly")
        self.payment_property_combo.grid(row=0, column=3, padx=5, pady=10)
        
        # 筛选按钮使用主按钮样式
        ttk.Button(filter_frame, text="筛选", command=self.filter_payments, style='Primary.TButton').grid(row=0, column=4, padx=5, pady=10)
        
        # 记录总条数和实收金额总和显示标签（移动至重置按钮之前，同一行显示）
        self.total_amount_label = ttk.Label(filter_frame, text="共0条记录，总金额：0.00元", font= ("SimHei", 10), foreground="green")
        self.total_amount_label.grid(row=1, column=0, columnspan=3, padx=15, pady=10, sticky=tk.W)
        
        ttk.Button(filter_frame, text="重置", command=self.reset_filters).grid(row=1, column=4, padx=5, pady=10)
        
        # 收款记录 - 使用卡片样式美化
        records_frame = ttk.LabelFrame(payment_frame, text="收款记录", padding=10, style='Card.TFrame')
        records_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        columns = ("序号", "物业名称", "账单月份", "实收金额", "缴费人", "缴费日期", "操作人")
        self.payments_tree = ttk.Treeview(records_frame, columns=columns, show="headings", height=10)
        
        for col in columns:
            self.payments_tree.heading(col, text=col)
            if col == "序号":
                self.payments_tree.column(col, width=60, anchor=tk.CENTER)
            else:
                self.payments_tree.column(col, width=120)
        
        scrollbar2 = ttk.Scrollbar(records_frame, orient=tk.VERTICAL, command=self.payments_tree.yview)
        self.payments_tree.configure(yscrollcommand=scrollbar2.set)
        
        self.payments_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar2.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 初始化筛选下拉框
        self.init_payment_filters()
        
        # 加载数据
        self.load_bills()
        self.load_payments()
    
    # === 基础信息管理方法 ===
    def load_properties(self):
        """加载物业列表"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM properties ORDER BY type DESC, name ASC")
        rows = cursor.fetchall()
        conn.close()
        
        # 清空表格
        for item in self.property_tree.get_children():
            self.property_tree.delete(item)
        
        # 插入数据，并添加序号
        for index, row in enumerate(rows, start=1):
            # 转换为列表以便修改
            row_list = list(row)
            # 在ID列前插入序号
            row_list.insert(0, str(index))
            # 添加到表格
            self.property_tree.insert("", tk.END, values=tuple(row_list))
    
    def add_property(self):
        """新增物业"""
        name = self.name_entry.get().strip()
        property_type = self.type_combo.get().strip()
        area = self.area_entry.get().strip()
        contact = self.contact_entry.get().strip()
        phone = self.phone_entry.get().strip()
        
        if not name or not property_type:
            messagebox.showerror("错误", "请填写名称和类型！")
            return
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            cursor.execute('''
                INSERT INTO properties (name, type, area, contact_person, contact_phone)
                VALUES (?, ?, ?, ?, ?)
            ''', (name, property_type, area, contact, phone))
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", "物业信息添加成功！")
            self.clear_property_form()
            self.load_properties()
            self.update_reading_combos()
            
        except Exception as e:
            messagebox.showerror("错误", f"添加失败: {str(e)}")
    
    def on_property_select(self, event):
        """选择物业事件"""
        selection = self.property_tree.selection()
        if selection:
            item = self.property_tree.item(selection[0])
            values = item['values']
            
            # 填充表单（列顺序：序号, ID, 名称, 类型, 面积, 联系人, 联系电话, 状态）
            self.name_entry.delete(0, tk.END)
            self.name_entry.insert(0, values[2])
            self.type_combo.set(values[3])
            self.area_entry.delete(0, tk.END)
            self.area_entry.insert(0, values[4] if values[4] else "")
            self.contact_entry.delete(0, tk.END)
            self.contact_entry.insert(0, values[5] if values[5] else "")
            self.phone_entry.delete(0, tk.END)
            self.phone_entry.insert(0, values[6] if values[6] else "")
    
    def update_property(self):
        """修改物业信息"""
        selection = self.property_tree.selection()
        if not selection:
            messagebox.showerror("错误", "请选择要修改的物业！")
            return
        
        item = self.property_tree.item(selection[0])
        property_id = item['values'][1]  # 由于添加了序号列，索引需要+1
        
        name = self.name_entry.get().strip()
        property_type = self.type_combo.get().strip()
        area = self.area_entry.get().strip()
        contact = self.contact_entry.get().strip()
        phone = self.phone_entry.get().strip()
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            cursor.execute('''
                UPDATE properties 
                SET name=?, type=?, area=?, contact_person=?, contact_phone=?
                WHERE id=?
            ''', (name, property_type, area, contact, phone, property_id))
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", "物业信息修改成功！")
            self.load_properties()
            self.update_reading_combos()
            
        except Exception as e:
            messagebox.showerror("错误", f"修改失败: {str(e)}")
    
    def delete_property(self):
        """删除物业信息"""
        selection = self.property_tree.selection()
        if not selection:
            messagebox.showerror("错误", "请选择要删除的物业！")
            return
        
        # 验证密码
        if not self.verify_password("删除物业信息"):
            messagebox.showerror("权限不足", "您需要输入密码才能删除物业信息！")
            return
        
        item = self.property_tree.item(selection[0])
        property_id = item['values'][1]  # 由于添加了序号列，索引需要+1
        
        # 检查物业是否存在业务关联
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 检查是否有抄表记录
            cursor.execute("SELECT COUNT(*) FROM meter_readings WHERE property_id=?", (property_id,))
            meter_count = cursor.fetchone()[0]
            
            # 检查是否有收款记录
            cursor.execute("SELECT COUNT(*) FROM payments WHERE property_id=?", (property_id,))
            payment_count = cursor.fetchone()[0]
            
            conn.close()
            
            # 如果有任何业务关联，禁止删除
            if meter_count > 0 or payment_count > 0:
                messagebox.showerror("错误", "该物业名称已被使用，不能删除！")
                return
        except Exception as e:
            messagebox.showerror("错误", f"检查失败: {str(e)}")
            return
        
        # 执行删除操作
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            cursor.execute("DELETE FROM properties WHERE id=?", (property_id,))
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", "物业信息删除成功！")
            self.clear_property_form()
            self.load_properties()
            self.update_reading_combos()
            
        except Exception as e:
            messagebox.showerror("错误", f"删除失败: {str(e)}")
    
    def clear_property_form(self):
        """清空物业表单"""
        self.name_entry.delete(0, tk.END)
        self.type_combo.set('')
        self.area_entry.delete(0, tk.END)
        self.contact_entry.delete(0, tk.END)
        self.phone_entry.delete(0, tk.END)
    
    # === 收费标准管理方法 ===
    def load_property_types(self):
        """加载所有可用的物业类型"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT property_type FROM price_config ORDER BY property_type")
        types = [row[0] for row in cursor.fetchall()]
        conn.close()
        
        # 去重处理，确保不会显示重复的类型
        unique_types = list(dict.fromkeys(types))  # 使用字典保持原始顺序并去重
        self.type_combo['values'] = unique_types
        if unique_types:
            self.type_combo.current(0)
            
    def load_price_types(self):
        """加载所有收费标准类型"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT property_type FROM price_config ORDER BY property_type")
        types = [row[0] for row in cursor.fetchall()]
        conn.close()
        
        # 去重处理，确保不会显示重复的类型
        unique_types = list(dict.fromkeys(types))  # 使用字典保持原始顺序并去重
        self.price_type_combo['values'] = unique_types
        if unique_types:
            self.price_type_combo.current(0)
            self.on_price_type_selected(None)  # 加载第一个类型的价格
    
    def on_price_type_selected(self, event):
        """选择收费类型时加载对应的价格"""
        selected_type = self.price_type_combo.get()
        if selected_type:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            # 获取该物业类型的最新价格记录（通过MAX(id)确定）
            cursor.execute("SELECT water_price, electricity_price FROM price_config WHERE id=(SELECT MAX(id) FROM price_config WHERE property_type=?)", (selected_type,))
            prices = cursor.fetchone()
            conn.close()
            
            if prices:
                self.water_price_entry.delete(0, tk.END)
                self.water_price_entry.insert(0, str(prices[0]))
                self.electricity_price_entry.delete(0, tk.END)
                self.electricity_price_entry.insert(0, str(prices[1]))
    
    def on_price_list_select(self, event):
        """选择收费标准列表中的记录时更新表单"""
        selection = self.price_tree.selection()
        if selection:
            item = selection[0]
            property_type = self.price_tree.item(item, "values")[0]
            # 查找价格类型下拉框中是否存在该类型
            type_values = list(self.price_type_combo['values'])
            if property_type in type_values:
                # 设置下拉框的选中值
                self.price_type_combo.set(property_type)
                # 触发价格加载
                self.on_price_type_selected(None)
    
    def load_price_list(self):
        """加载收费标准列表数据，确保不显示重复记录并显示最新价格"""
        # 清空现有数据
        for item in self.price_tree.get_children():
            self.price_tree.delete(item)
        
        # 从数据库加载数据，选择每个物业类型的最新记录（通过MAX(id)确定）
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT property_type, water_price, electricity_price FROM price_config WHERE id IN (SELECT MAX(id) FROM price_config GROUP BY property_type) ORDER BY property_type")
        prices = cursor.fetchall()
        conn.close()
        
        # 添加数据到列表
        for price in prices:
            self.price_tree.insert('', tk.END, values=(price[0], price[1], price[2]))
            
    def load_price_types(self):
        """加载所有收费标准类型并更新收费标准列表"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT property_type FROM price_config ORDER BY property_type")
        types = [row[0] for row in cursor.fetchall()]
        conn.close()
        
        # 去重处理，确保不会显示重复的类型
        unique_types = list(dict.fromkeys(types))  # 使用字典保持原始顺序并去重
        self.price_type_combo['values'] = unique_types
        if unique_types:
            self.price_type_combo.current(0)
            self.on_price_type_selected(None)  # 加载第一个类型的价格
        
        # 更新收费标准列表
        self.load_price_list()
    
    def add_price_type(self):
        """添加新的收费标准类型"""
        new_type = self.new_type_entry.get().strip()
        if not new_type:
            messagebox.showerror("错误", "请输入新的收费类型名称！")
            return
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 检查类型是否已存在
            cursor.execute("SELECT COUNT(*) FROM price_config WHERE property_type=?", (new_type,))
            if cursor.fetchone()[0] > 0:
                messagebox.showerror("错误", "该收费类型已存在！")
                conn.close()
                return
            
            # 插入新类型，默认价格设为0
            cursor.execute('''
                INSERT INTO price_config (property_type, water_price, electricity_price, effective_date)
                VALUES (?, 0, 0, ?)
            ''', (new_type, datetime.now().strftime("%Y-%m-%d")))
            
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", f"新增收费类型'{new_type}'成功！")
            self.new_type_entry.delete(0, tk.END)
            self.load_price_types()  # 刷新类型列表
            
            # 同时更新基础信息管理页面和报表页面的类型下拉框
            if hasattr(self, 'type_combo'):
                current_types = list(self.type_combo['values'])
                if new_type not in current_types:
                    current_types.append(new_type)
                    self.type_combo['values'] = current_types
            
            # 重新加载报表页面的物业类型
            if hasattr(self, 'load_report_property_types'):
                self.load_report_property_types()
                    
        except Exception as e:
            messagebox.showerror("错误", f"添加失败: {str(e)}")
    
    def delete_price_type(self):
        """删除收费标准类型"""
        selected_type = self.price_type_combo.get()
        if not selected_type:
            messagebox.showerror("错误", "请先选择要删除的收费类型！")
            return
        
        # 不能删除系统默认的两种类型
        if selected_type in ['门面', '办公室']:
            messagebox.showerror("错误", "系统默认类型不能删除！")
            return
        
        # 验证密码
        if not self.verify_password("删除收费标准类型"):
            messagebox.showerror("权限不足", "您需要输入密码才能删除收费标准类型！")
            return
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 删除收费类型
            cursor.execute("DELETE FROM price_config WHERE property_type=?", (selected_type,))
            
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", f"收费类型'{selected_type}'已删除！")
            self.load_price_types()  # 刷新类型列表
            
            # 同时更新基础信息管理页面和报表页面的类型下拉框
            if hasattr(self, 'type_combo'):
                current_types = list(self.type_combo['values'])
                if selected_type in current_types:
                    current_types.remove(selected_type)
                    self.type_combo['values'] = current_types
            
            # 重新加载报表页面的物业类型
            if hasattr(self, 'load_report_property_types'):
                self.load_report_property_types()
                    
        except Exception as e:
            messagebox.showerror("错误", f"删除失败: {str(e)}")
    
    def load_prices(self):
        """加载收费标准（保持向后兼容）"""
        self.load_price_types()
    
    def save_prices(self):
        """保存收费标准并更新列表"""
        selected_type = self.price_type_combo.get()
        if not selected_type:
            messagebox.showerror("错误", "请先选择收费类型！")
            return
        
        try:
            water_price = float(self.water_price_entry.get())
            electricity_price = float(self.electricity_price_entry.get())
            
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            cursor.execute('''
                UPDATE price_config 
                SET water_price=?, electricity_price=?, effective_date=?
                WHERE property_type=?
            ''', (water_price, electricity_price, datetime.now().strftime("%Y-%m-%d"), selected_type))
            
            conn.commit()
            conn.close()
            
            # 更新收费标准列表
            self.load_price_list()
            
            messagebox.showinfo("成功", f"{selected_type}收费标准保存成功！")
            
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字！")
    
    def on_property_selected(self, event=None):
        """物业选择变化时更新物业类型标签"""
        property_str = self.reading_property_combo.get()
        if property_str:
            try:
                property_id = property_str.split('-')[0]
                conn = sqlite3.connect('water_electricity.db')
                cursor = conn.cursor()
                cursor.execute("SELECT type FROM properties WHERE id=?", (property_id,))
                property_type = cursor.fetchone()[0]
                conn.close()
                self.property_type_label.config(text=f"({property_type})", foreground="black")
            except:
                self.property_type_label.config(text="(物业类型)", foreground="gray")
    
    # === 抄表与计算方法 ===
    def update_reading_combos(self):
        """更新抄表页面的下拉框"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT id, name FROM properties")
        properties = cursor.fetchall()
        
        # 先从数据库获取所有已存在的抄表月份
        cursor.execute("SELECT DISTINCT strftime('%Y-%m', reading_date) FROM meter_readings ORDER BY strftime('%Y-%m', reading_date) DESC")
        db_months = [month[0] for month in cursor.fetchall()]
        conn.close()
        
        # 更新物业下拉框，添加"全部"选项
        self.reading_property_combo['values'] = ["全部"] + [f"{p[0]}-{p[1]}" for p in properties]
        
        # 如果数据库中有月份记录，使用这些月份；否则生成最近12个月份
        if db_months:
            months = db_months
        else:
            # 生成最近12个月份
            months = []
            current = datetime.now()
            for i in range(12):
                month = current - timedelta(days=30*i)
                months.append(month.strftime("%Y-%m"))
        
        # 添加"全部"选项
        self.reading_month_combo['values'] = ["全部"] + months
        if months:
            self.reading_month_combo.set(months[0])
        
        # 添加事件绑定，使物业和月份选择变化时自动加载上月数据
        self.reading_property_combo.bind("<<ComboboxSelected>>", self.on_property_month_change)
        self.reading_month_combo.bind("<<ComboboxSelected>>", self.on_property_month_change)
    
    def on_property_month_change(self, event):
        """物业或月份选择变化时自动加载上月数据"""
        # 先调用on_property_selected更新物业类型标签
        self.on_property_selected(event)
        
        # 获取当前选择的物业和月份
        property_str = self.reading_property_combo.get()
        month_str = self.reading_month_combo.get()
        
        # 如果物业选择不为"全部"且月份选择为"全部"，弹出提示
        if property_str and property_str != "全部" and month_str == "全部":
            messagebox.showinfo("提示", "请选择具体的月份，不能是'全部'")
            return
        
        # 确保物业和月份都已选择，并且物业不是"全部"
        if property_str and month_str and property_str != "全部" and month_str != "全部":
            # 直接调用load_previous_reading方法
            self.load_previous_reading()
    
    def update_report_month_combo(self):
        """更新报表页面的月份下拉框，包含所有已存在的抄表月份"""
        # 从数据库获取所有已存在的抄表月份
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT DISTINCT strftime('%Y-%m', reading_date) FROM meter_readings ORDER BY strftime('%Y-%m', reading_date) DESC")
        db_months = [month[0] for month in cursor.fetchall()]
        conn.close()
        
        # 如果数据库中有月份记录，使用这些月份；否则生成最近12个月份
        if db_months:
            months = db_months
        else:
            # 生成最近12个月份
            months = []
            current = datetime.now()
            for i in range(12):
                month = current - timedelta(days=30*i)
                months.append(month.strftime("%Y-%m"))
        
        # 添加"全部"选项
        self.report_month_combo['values'] = ["全部"] + months
        if months:
            self.report_month_combo.set(months[0])
    
    def load_previous_reading(self):
        """加载上月读数"""
        property_str = self.reading_property_combo.get()
        if not property_str:
            messagebox.showerror("错误", "请选择物业！")
            return
        
        property_id = property_str.split('-')[0]
        current_month = self.reading_month_combo.get()
        
        # 检查月份是否为"全部"
        if current_month == "全部":
            messagebox.showerror("错误", "请选择具体的月份，不能是'全部'！")
            return
            
        # 计算上个月
        try:
            current_date = datetime.strptime(current_month + "-01", "%Y-%m-%d")
            previous_date = current_date - timedelta(days=30)
            previous_month = previous_date.strftime("%Y-%m")
        except ValueError:
            messagebox.showerror("错误", "月份格式不正确，请选择有效的月份！")
            return
        
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute('''
            SELECT water_current, electricity_current 
            FROM meter_readings 
            WHERE property_id=? AND strftime('%Y-%m', reading_date)=?
        ''', (property_id, previous_month))
        
        result = cursor.fetchone()
        conn.close()
        
        if result:
            self.water_previous.delete(0, tk.END)
            self.water_previous.insert(0, str(result[0]))
            self.electricity_previous.delete(0, tk.END)
            self.electricity_previous.insert(0, str(result[1]))
        else:
            messagebox.showwarning("提示", f"未找到{previous_month}的抄表记录，请手动录入上月读数。")
    
    def round_to_nearest(self, value):
        """自定义四舍五入函数，确保0.5向上舍入"""
        integer_part = int(value)
        decimal_part = value - integer_part
        if decimal_part >= 0.5:
            return integer_part + 1
        else:
            return integer_part
            
    def calculate_amount(self):
        """计算费用"""
        try:
            # 获取输入数据
            water_prev = float(self.water_previous.get() or 0)
            water_curr = float(self.water_current.get() or 0)
            water_adj = float(self.water_adjustment.get() or 0)
            elec_prev = float(self.electricity_previous.get() or 0)
            elec_curr = float(self.electricity_current.get() or 0)
            elec_adj = float(self.electricity_adjustment.get() or 0)
            
            # 获取物业类型和收费标准
            property_str = self.reading_property_combo.get()
            if not property_str:
                messagebox.showerror("错误", "请选择物业！")
                return
            
            property_id = property_str.split('-')[0]
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 获取物业类型
            cursor.execute("SELECT type FROM properties WHERE id=?", (property_id,))
            property_type = cursor.fetchone()[0]
            
            # 获取最新的收费标准
            cursor.execute("SELECT water_price, electricity_price FROM price_config WHERE id=(SELECT MAX(id) FROM price_config WHERE property_type=?)", (property_type,))
            prices = cursor.fetchone()
            conn.close()
            
            if not prices:
                messagebox.showerror("错误", "未找到对应的收费标准！")
                return
            
            water_price, electricity_price = prices
            
            # 计算用量和费用
            water_usage = water_curr - water_prev + water_adj
            electricity_usage = elec_curr - elec_prev + elec_adj
            
            # 计算金额（四舍五入到元）
            water_amount = self.round_to_nearest(water_usage * water_price)
            electricity_amount = self.round_to_nearest(electricity_usage * electricity_price)
            # 确保总金额准确计算（水费+电费）
            total_amount = self.round_to_nearest(water_amount + electricity_amount)
            
            # 调试信息：显示计算的总金额值
            print(f"计算的水费: {water_amount}, 电费: {electricity_amount}, 总金额: {total_amount}")
            # messagebox.showinfo("调试信息", f"计算的水费: {water_amount}, 电费: {electricity_amount}, 总金额: {total_amount}")
            
            # 显示结果
            self.water_amount_label.config(text=f"{water_amount}元")
            self.electricity_amount_label.config(text=f"{electricity_amount}元")
            # 使用StringVar设置总金额
            self.total_amount_var.set(f"{total_amount}元")
            
            # 强制刷新UI，确保标签值正确显示
            self.water_amount_label.update()
            self.electricity_amount_label.update()
            self.total_amount_label.update()
            # 尝试使用root窗口的update方法
            self.root.update()
            
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字！")
    
    def save_reading(self):
        """保存抄表记录"""
        property_str = self.reading_property_combo.get()
        if not property_str:
            messagebox.showerror("错误", "请选择物业！")
            return
        
        property_id = property_str.split('-')[0]
        reading_month = self.reading_month_combo.get()
        
        try:
            # 获取数据
            water_prev = float(self.water_previous.get() or 0)
            water_curr = float(self.water_current.get() or 0)
            water_adj = float(self.water_adjustment.get() or 0)
            elec_prev = float(self.electricity_previous.get() or 0)
            elec_curr = float(self.electricity_current.get() or 0)
            elec_adj = float(self.electricity_adjustment.get() or 0)
            
            # 从标签获取水费和电费金额
            water_amount = float(self.water_amount_label.cget("text").replace("元", ""))
            electricity_amount = float(self.electricity_amount_label.cget("text").replace("元", ""))
            # 从StringVar获取总金额（因为总金额标签使用了textvariable绑定）
            total_amount = float(self.total_amount_var.get().replace("元", ""))
            
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 检查是否已存在该月记录
            reading_date = reading_month + "-01"
            cursor.execute('''
                SELECT id FROM meter_readings 
                WHERE property_id=? AND strftime('%Y-%m', reading_date)=?
            ''', (property_id, reading_month))
            
            existing_id = cursor.fetchone()
            
            if existing_id:
                # 检查现有记录的状态是否为'已收款'
                cursor.execute('''
                    SELECT p2.status FROM payments p2 
                    WHERE p2.property_id=? AND strftime('%Y-%m', p2.billing_date)=?
                ''', (property_id, reading_month))
                payment_status = cursor.fetchone()
                
                if payment_status and payment_status[0] == '已付款':
                    # 获取物业名称用于提示信息
                    cursor.execute("SELECT name FROM properties WHERE id=?", (property_id,))
                    property_name = cursor.fetchone()[0]
                    messagebox.showerror("错误", f"该笔记录（{property_name}|{reading_month}）已收款完成，不能进行修改！")
                    conn.close()
                    return
                
                if messagebox.askyesno("确认", "该月份已有抄表记录，是否覆盖？"):
                    # 更新现有记录
                    cursor.execute('''
                        UPDATE meter_readings 
                        SET water_previous=?, water_current=?, electricity_previous=?, 
                            electricity_current=?, water_adjustment=?, electricity_adjustment=?, 
                            water_amount=?, electricity_amount=?, total_amount=?
                        WHERE id=?
                    ''', (water_prev, water_curr, elec_prev, 
                          elec_curr, water_adj, elec_adj, water_amount, electricity_amount, total_amount, existing_id[0]))
                else:
                    conn.close()
                    return
            else:
                # 插入新记录
                cursor.execute('''
                    INSERT INTO meter_readings 
                    (property_id, reading_date, water_previous, water_current, electricity_previous, 
                     electricity_current, water_adjustment, electricity_adjustment, 
                     water_amount, electricity_amount, total_amount)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                ''', (property_id, reading_date, water_prev, water_curr, elec_prev, 
                      elec_curr, water_adj, elec_adj, water_amount, electricity_amount, total_amount))
            
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", "抄表记录保存成功！")
            self.load_reading_history()
            
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字！")
    
    def generate_bill(self):
        """生成账单 - 支持对'抄表明细记录'列表内状态为'未收款'的记录执行批量操作"""
        # 询问用户是否要批量生成所有未收款记录的账单
        result = messagebox.askyesno("批量生成", "是否批量生成所有状态为'未收款'的记录的账单？\n\n选择'是'将为所有符合条件的记录生成账单\n选择'否'将只为当前选中的记录生成账单")
        
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        
        if result:
            # 批量生成模式
            # 获取所有状态为'未收款'的记录
            cursor.execute('''
                SELECT mr.id, p.name, strftime('%Y-%m', mr.reading_date), mr.property_id, mr.total_amount
                FROM meter_readings mr
                LEFT JOIN properties p ON mr.property_id = p.id
                WHERE NOT EXISTS (
                    SELECT 1 FROM payments pm 
                    WHERE pm.property_id = mr.property_id 
                    AND strftime('%Y-%m', pm.billing_date) = strftime('%Y-%m', mr.reading_date)
                )
            ''')
            
            unpaid_records = cursor.fetchall()
            
            if not unpaid_records:
                conn.close()
                messagebox.showinfo("提示", "没有需要生成账单的未收款记录！")
                return
            
            # 记录成功和失败的数量
            success_count = 0
            failed_count = 0
            
            for record in unpaid_records:
                record_id, property_name, reading_month, property_id, total_amount = record
                
                try:
                    # 检查是否已存在账单（再次检查避免并发问题）
                    cursor.execute('''
                        SELECT id FROM payments 
                        WHERE property_id=? AND strftime('%Y-%m', billing_date)=?
                    ''', (property_id, reading_month))
                    
                    if not cursor.fetchone():
                        # 创建新账单
                        billing_date = reading_month + "-01"
                        cursor.execute('''
                            INSERT INTO payments (property_id, billing_date, amount, status)
                            VALUES (?, ?, ?, '待付款')
                        ''', (property_id, billing_date, total_amount))
                        success_count += 1
                    else:
                        failed_count += 1
                except Exception as e:
                    print(f"生成账单失败：{str(e)}")
                    failed_count += 1
            
            conn.commit()
            conn.close()
            
            messagebox.showinfo("批量生成完成", f"批量生成账单完成！\n\n成功生成: {success_count}条\n跳过或失败: {failed_count}条")
        else:
            # 单条生成模式
            # 检查是否有选中的记录
            selection = self.reading_details_tree.selection()
            if not selection:
                conn.close()
                messagebox.showerror("错误", "请先在'抄表明细记录'中选择一条记录！")
                return
            
            # 获取选中记录的数据
            item = self.reading_details_tree.item(selection[0])
            record_data = item['values']
            
            # 检查记录状态是否为'未收款'（状态是第13列，索引为12）
            if record_data[13] != "未收款":
                conn.close()
                messagebox.showwarning("提示", "只能对状态为'未收款'的记录生成账单！")
                return
            
            # 从选中记录中获取物业名称、月份和总金额
            # 注意：record_data中存储的是显示值，需要从数据库获取完整记录
            record_id = item['tags'][0]  # 获取记录ID
            
            # 从数据库获取完整的抄表记录
            cursor.execute('''
                SELECT mr.property_id, strftime('%Y-%m', mr.reading_date), mr.total_amount
                FROM meter_readings mr
                WHERE mr.id = ?
            ''', (record_id,))
            
            db_record = cursor.fetchone()
            if not db_record:
                conn.close()
                messagebox.showerror("错误", "未找到对应的抄表记录！")
                return
            
            property_id, reading_month, total_amount = db_record
            
            # 检查是否已存在账单
            cursor.execute('''
                SELECT id FROM payments 
                WHERE property_id=? AND strftime('%Y-%m', billing_date)=?
            ''', (property_id, reading_month))
            
            if cursor.fetchone():
                conn.close()
                messagebox.showwarning("提示", "该月份账单已存在！")
                return
            
            # 创建新账单
            billing_date = reading_month + "-01"
            cursor.execute('''
                INSERT INTO payments (property_id, billing_date, amount, status)
                VALUES (?, ?, ?, '待付款')
            ''', (property_id, billing_date, total_amount))
            
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", f"已为'{record_data[2]}'生成{reading_month}月份账单！")
        
        # 重新加载抄表历史记录以更新状态
        self.load_reading_history()
        self.load_bills()
    
    def export_to_excel(self):
        """导出Excel功能：将抄表明细记录导出为Excel文件"""
        # 检查openpyxl库是否可用
        if not OPENPYXL_AVAILABLE:
            messagebox.showerror("错误", "未安装openpyxl库，请先安装: pip install openpyxl")
            return
        
        # 获取当前选择的物业和抄表月份
        property_str = self.reading_property_combo.get()
        reading_month = self.reading_month_combo.get()
        
        # 移除月份必须选择具体值的限制
        # if not reading_month or reading_month == "全部":
        #     messagebox.showwarning("提示", "请先选择一个具体的抄表月份！")
        #     return
        
        try:
            # 创建Excel工作簿
            wb = openpyxl.Workbook()
            ws = wb.active
            
            # 设置表格标题
            if reading_month and reading_month != "全部":
                title = f"{reading_month}水电费抄表记录明细表"
            else:
                title = f"所有月份水电费抄表记录明细表"
            
            if property_str and property_str != "全部":
                property_name = property_str.split('-')[1]
                title = f"{title.split('水电')[0]}{property_name}水电{title.split('水电')[1]}"
            ws['A1'] = title
            
            # 设置表格标题样式：合并单元格、加粗、居中、大字体
            last_column = 'N'  # 总共14列（包含序号列）
            ws.merge_cells(f'A1:{last_column}1')
            title_cell = ws['A1']
            title_cell.font = Font(bold=True, size=16)
            title_cell.alignment = Alignment(horizontal='center', vertical='center')
            
            # 设置表头标题行
            headers = ["序号", "ID", "物业名称", "月份", "水表读数", "水表调整量", 
                      "水用量\吨", "水费\元", "电表读数", "电表调整量", 
                      "电用量\度", "电费\元", "总金额\元", "状态"]
            
            # 设置表头样式：背景色、加粗、居中
            header_fill = PatternFill(start_color='DDEBF7', end_color='DDEBF7', fill_type='solid')
            header_font = Font(bold=True)
            header_alignment = Alignment(horizontal='center', vertical='center')
            
            # 设置边框样式
            thin_border = Border(
                left=Side(style='thin'),
                right=Side(style='thin'),
                top=Side(style='thin'),
                bottom=Side(style='thin')
            )
            
            # 添加表头
            for col_idx, header in enumerate(headers, 1):
                cell = ws.cell(row=2, column=col_idx)
                cell.value = header
                cell.fill = header_fill
                cell.font = header_font
                cell.alignment = header_alignment
                cell.border = thin_border
            
            # 获取抄表明细数据
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 根据是否选择了物业和月份构建查询条件
            query = '''
                SELECT 
                    mr.id,
                    p.name,
                    strftime('%Y-%m', mr.reading_date),
                    mr.water_previous || ' → ' || mr.water_current,
                    mr.water_adjustment,
                    (mr.water_current - mr.water_previous + mr.water_adjustment),
                    mr.water_amount,
                    mr.electricity_previous || ' → ' || mr.electricity_current,
                    mr.electricity_adjustment,
                    (mr.electricity_current - mr.electricity_previous + mr.electricity_adjustment),
                    mr.electricity_amount,
                    mr.total_amount,
                    CASE WHEN EXISTS (
                        SELECT 1 FROM payments p2 
                        WHERE p2.property_id = mr.property_id 
                        AND strftime('%Y-%m', p2.billing_date) = strftime('%Y-%m', mr.reading_date)
                        AND p2.status = '已付款'
                    ) THEN '已收款' ELSE '未收款' END as status
                FROM meter_readings mr
                LEFT JOIN properties p ON mr.property_id = p.id
            '''
            
            params = []
            where_clauses = []
            
            # 物业筛选逻辑，如果选择了"全部"则不添加物业条件
            if property_str and property_str != "全部":
                property_id = property_str.split('-')[0]
                where_clauses.append("mr.property_id = ?")
                params.append(property_id)
            
            # 月份筛选逻辑，如果选择了"全部"则不添加月份条件
            if reading_month and reading_month != "全部":
                where_clauses.append("strftime('%Y-%m', mr.reading_date) = ?")
                params.append(reading_month)
            
            if where_clauses:
                query += " WHERE " + " AND ".join(where_clauses)
            
            query += " ORDER BY mr.reading_date DESC"
            cursor.execute(query, params)
            rows = cursor.fetchall()
            conn.close()
            
            if not rows:
                messagebox.showinfo("提示", f"未找到符合条件的抄表记录！")
                return
            
            # 添加数据行
            for row_idx, row_data in enumerate(rows, 3):
                # 序号 - 添加边框
                cell = ws.cell(row=row_idx, column=1)
                cell.value = row_idx - 2
                cell.alignment = Alignment(horizontal='center')
                cell.border = thin_border
                
                # 数据列
                for col_idx, value in enumerate(row_data, 2):
                    cell = ws.cell(row=row_idx, column=col_idx)
                    
                    # 格式化数值
                    if col_idx in [5, 6, 9, 10, 11, 12]:  # 数值类型的列
                        if isinstance(value, (int, float)):
                            cell.value = value
                            cell.alignment = Alignment(horizontal='right')
                        else:
                            cell.value = value
                            cell.alignment = Alignment(horizontal='left')
                    else:
                        cell.value = value
                        cell.alignment = Alignment(horizontal='left')
                    
                    # 添加边框
                    cell.border = thin_border
            
            # 调整列宽
            column_widths = {
                1: 8,    # 序号
                2: 8,    # ID
                3: 15,   # 物业名称
                4: 12,   # 月份
                5: 15,   # 水表读数
                6: 12,   # 水表调整量
                7: 10,   # 水用量
                8: 10,   # 水费
                9: 15,   # 电表读数
                10: 12,  # 电表调整量
                11: 10,  # 电用量
                12: 10,  # 电费
                13: 12,  # 总金额
                14: 10   # 状态
            }
            
            for col_idx, width in column_widths.items():
                ws.column_dimensions[openpyxl.utils.get_column_letter(col_idx)].width = width
            
            # 保存文件
            if reading_month and reading_month != "全部":
                file_name = f"{reading_month}水电费抄表记录明细表.xlsx"
            else:
                file_name = f"所有月份水电费抄表记录明细表.xlsx"
            
            if property_str and property_str != "全部":
                property_name = property_str.split('-')[1]
                file_name = f"{file_name.split('水电')[0]}{property_name}水电{file_name.split('水电')[1]}"
            
            file_path = os.path.join(os.getcwd(), file_name)
            wb.save(file_path)
            
            # 显示成功消息
            messagebox.showinfo("成功", f"Excel文件已导出至：\n{file_path}")
            
            # 自动打开Excel文件
            if os.path.exists(file_path):
                try:
                    webbrowser.open(file_path)
                except Exception as e:
                    messagebox.showwarning("提示", f"Excel文件已导出，但无法自动打开：{str(e)}")
        
        except Exception as e:
            messagebox.showerror("错误", f"导出Excel时发生错误：{str(e)}")
    
    # === 新增的抄表历史记录方法 ===
    def load_reading_history(self):
        """加载抄表历史记录"""
        property_str = self.reading_property_combo.get()
        reading_month = self.reading_month_combo.get()
        
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        
        # 根据是否选择了物业和月份构建查询条件
        query = '''
            SELECT 
                mr.id,
                p.name,
                strftime('%Y-%m', mr.reading_date),
                mr.water_previous || ' → ' || mr.water_current,
                mr.water_adjustment,
                (mr.water_current - mr.water_previous + mr.water_adjustment),
                mr.water_amount,
                mr.electricity_previous || ' → ' || mr.electricity_current,
                mr.electricity_adjustment,
                (mr.electricity_current - mr.electricity_previous + mr.electricity_adjustment),
                mr.electricity_amount,
                mr.total_amount,
                CASE WHEN EXISTS (
                    SELECT 1 FROM payments p2 
                    WHERE p2.property_id = mr.property_id 
                    AND strftime('%Y-%m', p2.billing_date) = strftime('%Y-%m', mr.reading_date)
                    AND p2.status = '已付款'
                ) THEN '已收款' ELSE '未收款' END as status
            FROM meter_readings mr
            LEFT JOIN properties p ON mr.property_id = p.id
        '''
        
        params = []
        where_clauses = []
        
        # 物业筛选逻辑，如果选择了"全部"则不添加物业条件
        if property_str and property_str != "全部":
            property_id = property_str.split('-')[0]
            where_clauses.append("mr.property_id = ?")
            params.append(property_id)
        
        # 月份筛选逻辑，如果选择了"全部"则不添加月份条件
        if reading_month and reading_month != "全部":
            where_clauses.append("strftime('%Y-%m', mr.reading_date) = ?")
            params.append(reading_month)
        
        if where_clauses:
            query += " WHERE " + " AND ".join(where_clauses)
        
        query += " ORDER BY mr.reading_date DESC, p.name ASC"
        cursor.execute(query, params)
        
        rows = cursor.fetchall()
        conn.close()
        
        # 清空表格
        for item in self.reading_details_tree.get_children():
            self.reading_details_tree.delete(item)
        
        # 插入数据
        for index, row in enumerate(rows, start=1):
            # 格式化金额显示
            formatted_row = list(row)
            formatted_row[6] = f"{round(row[6])}"  # 水费（无单位）
            formatted_row[10] = f"{round(row[10])}"  # 电费（无单位）
            formatted_row[11] = f"{round(row[11])}"  # 总金额（无单位）
            formatted_row[5] = f"{row[5]:.1f}"  # 水用量（无单位）
            formatted_row[9] = f"{row[9]:.1f}"  # 电用量（无单位）
            formatted_row[4] = f"{row[4]:.1f}"  # 水表调整量
            formatted_row[8] = f"{row[8]:.1f}"  # 电表调整量
            
            # 在ID列后插入序号
            formatted_row.insert(1, str(index))
            
            self.reading_details_tree.insert("", tk.END, values=formatted_row, tags=(row[0],))
        
        # 计算并更新统计数据
        if rows:
            # 统计记录条数
            records_count = len(rows)
            
            # 统计各项金额和用量
            total_water_amount = sum(row[6] for row in rows)
            total_electricity_amount = sum(row[10] for row in rows)
            total_amount = sum(row[11] for row in rows)
            total_water_usage = sum(row[5] for row in rows)
            total_electricity_usage = sum(row[9] for row in rows)
            
            # 更新统计标签
            self.records_count_label.config(text=f"记录条数: {records_count}")
            self.water_total_label.config(text=f"水费金额: {round(total_water_amount)}元")
            self.electricity_total_label.config(text=f"电费金额: {round(total_electricity_amount)}元")
            self.total_amount_total_label.config(text=f"总金额: {round(total_amount)}元")
            self.water_usage_label.config(text=f"水用量: {total_water_usage:.1f}吨")
            self.electricity_usage_label.config(text=f"电用量: {total_electricity_usage:.1f}度")
        else:
            # 如果没有记录，重置统计标签
            self.records_count_label.config(text="记录条数: 0")
            self.water_total_label.config(text="水费金额: 0元")
            self.electricity_total_label.config(text="电费金额: 0元")
            self.total_amount_total_label.config(text="总金额: 0元")
            self.water_usage_label.config(text="水用量: 0吨")
            self.electricity_usage_label.config(text="电用量: 0度")
    
    def on_reading_record_select(self, event):
        """选择抄表记录事件"""
        selection = self.reading_details_tree.selection()
        if selection:
            item = self.reading_details_tree.item(selection[0])
            record_id = item['tags'][0]  # 获取记录ID
            
            # 从数据库加载完整记录（包含物业信息）
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            cursor.execute('''
                SELECT mr.reading_date, mr.water_previous, mr.water_current, mr.water_adjustment,
                       mr.electricity_previous, mr.electricity_current, mr.electricity_adjustment,
                       mr.water_amount, mr.electricity_amount, mr.total_amount,
                       p.id, p.name
                FROM meter_readings mr
                LEFT JOIN properties p ON mr.property_id = p.id
                WHERE mr.id = ?
            ''', (record_id,))
            
            record = cursor.fetchone()
            conn.close()
            
            if record:
                # 更新月份选择
                reading_date = datetime.strptime(record[0], "%Y-%m-%d")
                month_str = reading_date.strftime("%Y-%m")
                self.reading_month_combo.set(month_str)
                
                # 更新物业选择框（使用ID-名称格式）
                property_value = f"{record[10]}-{record[11]}"
                self.reading_property_combo.set(property_value)
                
                # 同步更新物业类型标签
                self.on_property_selected()
                
                # 填充表单数据
                self.water_previous.delete(0, tk.END)
                self.water_previous.insert(0, str(record[1]))
                self.water_current.delete(0, tk.END)
                self.water_current.insert(0, str(record[2]))
                self.water_adjustment.delete(0, tk.END)
                self.water_adjustment.insert(0, str(record[3]))
                
                self.electricity_previous.delete(0, tk.END)
                self.electricity_previous.insert(0, str(record[4]))
                self.electricity_current.delete(0, tk.END)
                self.electricity_current.insert(0, str(record[5]))
                self.electricity_adjustment.delete(0, tk.END)
                self.electricity_adjustment.insert(0, str(record[6]))
                
                # 更新计算结果显示
                self.water_amount_label.config(text=f"{round(record[7])}元")
                self.electricity_amount_label.config(text=f"{round(record[8])}元")
                # 使用StringVar变量的set方法更新总金额标签，确保即时更新
                self.total_amount_var.set(f"{round(record[9])}元")
    
    def edit_reading_record(self):
        """编辑选中的抄表记录"""
        selection = self.reading_details_tree.selection()
        if not selection:
            messagebox.showerror("错误", "请选择要编辑的记录！")
            return
        
        # 检查表单数据是否完整
        if not self.validate_reading_form():
            return
        
        item = self.reading_details_tree.item(selection[0])
        record_id = item['tags'][0]
        
        # 检查记录状态是否为'已收款'
        # 由于在load_reading_history方法中插入了序号列，实际状态列索引为13
        record_data = item['values']
        if record_data[13] == "已收款":
            # 获取序号、物业名称和月份信息
            seq_num = record_data[0]  # 序号
            property_name = record_data[1]  # 物业名称
            month = record_data[2]  # 月份
            messagebox.showerror("错误", f"该笔记录（{seq_num}|{property_name}|{month}）已收款完成，不能进行修改！")
            return
        
        try:
            # 获取表单数据
            water_prev = float(self.water_previous.get() or 0)
            water_curr = float(self.water_current.get() or 0)
            water_adj = float(self.water_adjustment.get() or 0)
            elec_prev = float(self.electricity_previous.get() or 0)
            elec_curr = float(self.electricity_current.get() or 0)
            elec_adj = float(self.electricity_adjustment.get() or 0)
            
            water_amount = float(self.water_amount_label.cget("text").replace("元", ""))
            electricity_amount = float(self.electricity_amount_label.cget("text").replace("元", ""))
            total_amount = float(self.total_amount_label.cget("text").replace("元", ""))
            
            property_str = self.reading_property_combo.get()
            property_id = property_str.split('-')[0]
            reading_month = self.reading_month_combo.get()
            reading_date = reading_month + "-01"
            
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 更新抄表记录
            cursor.execute('''
                UPDATE meter_readings 
                SET water_previous=?, water_current=?, water_adjustment=?,
                    electricity_previous=?, electricity_current=?, electricity_adjustment=?,
                    water_amount=?, electricity_amount=?, total_amount=?,
                    reading_date=?
                WHERE id=?
            ''', (water_prev, water_curr, water_adj, elec_prev, elec_curr, elec_adj,
                  water_amount, electricity_amount, total_amount, reading_date, record_id))
            
            # 同时更新对应的账单金额
            cursor.execute('''
                UPDATE payments 
                SET amount=?
                WHERE property_id=? AND strftime('%Y-%m', billing_date)=?
            ''', (total_amount, property_id, reading_month))
            
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", "抄表记录更新成功！")
            self.load_reading_history()
            
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字！")
        except Exception as e:
            messagebox.showerror("错误", f"更新失败: {str(e)}")
    
    def cancel_bill(self):
        """取消待收款账单"""
        selection = self.bills_tree.selection()
        if not selection:
            messagebox.showerror("错误", "请选择要取消的账单记录！")
            return
        
        item = self.bills_tree.item(selection[0])
        bill_id = item['values'][0]
        
        if messagebox.askyesno("确认取消", "确定要取消该待收款账单吗？此操作不可撤销！"):
            try:
                conn = sqlite3.connect('water_electricity.db')
                cursor = conn.cursor()
                
                # 删除账单记录
                cursor.execute('DELETE FROM payments WHERE id=?', (bill_id,))
                conn.commit()
                conn.close()
                
                messagebox.showinfo("成功", "账单已成功取消！")
                self.load_bills()  # 刷新账单列表
                
            except Exception as e:
                messagebox.showerror("错误", f"取消失败: {str(e)}")
    
    def delete_reading_record(self):
        """删除选中的抄表记录"""
        selection = self.reading_details_tree.selection()
        if not selection:
            messagebox.showerror("错误", "请选择要删除的记录！")
            return
        
        # 验证密码
        if not self.verify_password("删除抄表记录"):
            messagebox.showerror("权限不足", "您需要输入密码才能删除抄表记录！")
            return
        
        item = self.reading_details_tree.item(selection[0])
        record_id = item['tags'][0]
        
        # 检查记录状态是否为'已收款'
        # 由于在load_reading_history方法中插入了序号列，实际状态列索引为13
        record_data = item['values']
        if record_data[13] == "已收款":
            # 获取序号、物业名称和月份信息
            seq_num = record_data[0]  # 序号
            property_name = record_data[1]  # 物业名称
            month = record_data[2]  # 月份
            messagebox.showerror(
                title="操作受限",
                message=f"该笔记录（{seq_num}|{property_name}|{month}）已收款完成，不能删除！",
                default="ok"
            )
            return
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 获取记录信息用于删除对应账单
            cursor.execute('''
                SELECT property_id, strftime('%Y-%m', reading_date) 
                FROM meter_readings WHERE id=?
            ''', (record_id,))
            record_info = cursor.fetchone()
            
            if record_info:
                property_id, reading_month = record_info
                
                # 删除抄表记录
                cursor.execute("DELETE FROM meter_readings WHERE id=?", (record_id,))
                
                # 删除对应账单
                cursor.execute('''
                    DELETE FROM payments 
                    WHERE property_id=? AND strftime('%Y-%m', billing_date)=?
                ''', (property_id, reading_month))
            
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", "记录删除成功！")
            self.clear_reading_form()
            self.load_reading_history()
            self.load_bills()  # 刷新账单列表
            
        except Exception as e:
            messagebox.showerror("错误", f"删除失败: {str(e)}")
    
    def clear_reading_form(self):
        """清空抄表表单"""
        self.water_previous.delete(0, tk.END)
        self.water_current.delete(0, tk.END)
        self.water_adjustment.delete(0, tk.END)
        self.water_adjustment.insert(0, "0")
        
        self.electricity_previous.delete(0, tk.END)
        self.electricity_current.delete(0, tk.END)
        self.electricity_adjustment.delete(0, tk.END)
        self.electricity_adjustment.insert(0, "0")
        
        self.water_amount_label.config(text="0元")
        self.electricity_amount_label.config(text="0元")
        # 使用StringVar变量确保总金额标签正确重置
        self.total_amount_var.set("0元")
    
    def validate_reading_form(self):
        """验证抄表表单数据"""
        if not self.reading_property_combo.get():
            messagebox.showerror("错误", "请选择物业！")
            return False
        
        if not self.reading_month_combo.get():
            messagebox.showerror("错误", "请选择月份！")
            return False
        
        try:
            water_prev = float(self.water_previous.get() or 0)
            water_curr = float(self.water_current.get() or 0)
            elec_prev = float(self.electricity_previous.get() or 0)
            elec_curr = float(self.electricity_current.get() or 0)
            
            if water_curr < water_prev:
                if not messagebox.askyesno("确认", "水表本月读数小于上月读数，是否继续？"):
                    return False
            
            if elec_curr < elec_prev:
                if not messagebox.askyesno("确认", "电表本月读数小于上月读数，是否继续？"):
                    return False
                    
            return True
            
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字！")
            return False
    
    # === 报表生成方法 ===
    def generate_report(self):
        """生成报表"""
        month = self.report_month_combo.get()
        property_type = self.report_type_combo.get()
        property_str = self.report_property_combo.get()
        
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        
        # 构建查询条件
        query = '''
            SELECT 
                CASE WHEN EXISTS (
                    SELECT 1 FROM payments pm 
                    WHERE pm.property_id = mr.property_id 
                    AND strftime('%Y-%m', pm.billing_date) = strftime('%Y-%m', mr.reading_date)
                    AND pm.status = '已付款'
                ) THEN '已收款' ELSE '未收款' END as status,
                p.name, p.type, 
                strftime('%Y-%m', mr.reading_date) as month,
                mr.water_previous || '→' || mr.water_current as water_reading,
                (mr.water_current - mr.water_previous + mr.water_adjustment) as water_usage,
                mr.water_adjustment,
                mr.water_amount,
                mr.electricity_previous || '→' || mr.electricity_current as electricity_reading,
                (mr.electricity_current - mr.electricity_previous + mr.electricity_adjustment) as electricity_usage,
                mr.electricity_adjustment,
                mr.electricity_amount,
                mr.total_amount,
                mr.reading_date
            FROM meter_readings mr
            JOIN properties p ON mr.property_id = p.id
        '''
        params = []
        where_clauses = []
        
        # 月份筛选逻辑，如果选择了"全部"则不添加月份条件
        if month and month != "全部":
            where_clauses.append("strftime('%Y-%m', mr.reading_date) = ?")
            params.append(month)
        
        if property_type != "全部":
            where_clauses.append("p.type = ?")
            params.append(property_type)
        
        # 添加物业名称筛选条件
        if property_str and property_str != "全部":
            property_id = property_str.split('-')[0]
            where_clauses.append("p.id = ?")
            params.append(property_id)
        
        if where_clauses:
            query += " WHERE " + " AND ".join(where_clauses)
        
        # 添加排序逻辑
        query += " ORDER BY strftime('%Y-%m', mr.reading_date) DESC, p.name ASC"
        
        cursor.execute(query, params)
        rows = cursor.fetchall()
        conn.close()
        
        # 清空表格
        for item in self.report_tree.get_children():
            self.report_tree.delete(item)
        
        # 初始化金额累加器
        total_amount = 0
        total_water_amount = 0
        total_electricity_amount = 0
        
        # 插入数据并计算总金额
        for index, row in enumerate(rows, start=1):
            # 转换为列表以便修改
            row_list = list(row)
            # 将水费、电费和总金额四舍五入为整数
            try:
                row_list[7] = str(round(float(row_list[7]))) if row_list[7] is not None else "0"
                row_list[11] = str(round(float(row_list[11]))) if row_list[11] is not None else "0"
                row_list[12] = str(round(float(row_list[12]))) if row_list[12] is not None else "0"
            except (ValueError, TypeError):
                pass
            # 在首列前方插入序号
            row_list.insert(0, str(index))
            # 根据状态设置不同的标签
            tag = 'paid' if row[0] == '已收款' else 'unpaid'
            self.report_tree.insert("", tk.END, values=tuple(row_list), tags=(tag,))
            
            # 累加金额（因为插入了序号列，所以索引需要+1）
            try:
                total_water_amount += float(row[7]) if row[7] is not None else 0
                total_electricity_amount += float(row[11]) if row[11] is not None else 0
                total_amount += float(row[12]) if row[12] is not None else 0
            except (ValueError, TypeError):
                pass
        
 
        
        # 更新金额总和显示标签
        self.summary_label.config(text=f"总计: {len(rows)}条记录, 水费: {round(total_water_amount)}元  电费: {round(total_electricity_amount)}元  总金额: {round(total_amount)}元", 
                                 font= ("SimHei", 10), foreground="green")
    
    def export_property_data(self):
        """导出物业资料"""
        # 检查openpyxl库是否可用
        if not OPENPYXL_AVAILABLE:
            messagebox.showerror("错误", "请先安装openpyxl库：pip install openpyxl")
            return
        
        # 从数据库中查询所有物业记录
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute("SELECT id, name, type, area, contact_person, contact_phone, status FROM properties ORDER BY id ASC")
        rows = cursor.fetchall()
        conn.close()
        
        if not rows:
            messagebox.showinfo("提示", "没有物业数据可导出")
            return
        
        # 创建Excel工作簿
        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = "物业资料"
        
        # 设置表头样式：背景色、加粗、居中、边框
        header_fill = PatternFill(start_color='DDEBF7', end_color='DDEBF7', fill_type='solid')
        header_font = Font(bold=True)
        header_alignment = Alignment(horizontal='center', vertical='center')
        
        # 设置边框样式
        thin_border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        
        # 插入表格标题行
        title = "物业资料报表"
        title_cell = ws.cell(row=1, column=1)
        title_cell.value = title
        # 合并标题单元格到第7列(G列)
        ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=7)
        # 设置标题样式：加粗、居中、字体大小12
        title_cell.font = Font(bold=True, size=12)
        title_cell.alignment = Alignment(horizontal='center', vertical='center')
        
        # 设置表头（在第2行）
        headers = ["序号", "物业名称", "类型", "面积(㎡)", "联系人", "联系电话", "状态"]
        for col_idx, header in enumerate(headers, 1):
            cell = ws.cell(row=2, column=col_idx)
            cell.value = header
            cell.font = header_font
            cell.alignment = header_alignment
            cell.fill = header_fill
            cell.border = thin_border
        
        # 填充数据并设置边框
        for row_idx, row_data in enumerate(rows, 3):
            # 添加序号
            cell = ws.cell(row=row_idx, column=1)
            cell.value = row_idx - 2  # 序号从1开始
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = thin_border
            # 物业名称
            cell = ws.cell(row=row_idx, column=2)
            cell.value = row_data[1] if len(row_data) > 1 else ''
            cell.border = thin_border
            # 类型
            cell = ws.cell(row=row_idx, column=3)
            cell.value = row_data[2] if len(row_data) > 2 else ''
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = thin_border
            # 面积（保留一位小数）
            cell = ws.cell(row=row_idx, column=4)
            area_value = row_data[3] if len(row_data) > 3 else 0
            cell.value = float(area_value) if area_value else 0
            cell.number_format = '0.0'
            cell.alignment = Alignment(horizontal='right', vertical='center')
            cell.border = thin_border
            # 联系人
            cell = ws.cell(row=row_idx, column=5)
            cell.value = row_data[4] if len(row_data) > 4 else ''
            cell.border = thin_border
            # 联系电话
            cell = ws.cell(row=row_idx, column=6)
            cell.value = row_data[5] if len(row_data) > 5 else ''
            cell.border = thin_border
            # 状态
            cell = ws.cell(row=row_idx, column=7)
            cell.value = row_data[6] if len(row_data) > 6 else '正常'
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = thin_border
        
        # 添加统计行
        stat_row = len(rows) + 4
        # 合并统计行单元格
        ws.merge_cells(start_row=stat_row, start_column=1, end_row=stat_row, end_column=7)
        # 设置统计信息
        stat_cell = ws.cell(row=stat_row, column=1)
        stat_cell.value = f"统计信息：共{len(rows)}条物业记录"
        stat_cell.font = Font(bold=True)
        stat_cell.alignment = Alignment(horizontal='left', vertical='center')
        stat_cell.border = thin_border
        
        # 优化列宽，为不同类型的列设置合适的宽度
        column_widths = [8, 20, 10, 12, 15, 15, 10]  # 序号、物业名称等列宽
        for col_idx, width in enumerate(column_widths, 1):
            ws.column_dimensions[openpyxl.utils.get_column_letter(col_idx)].width = width
        
        # 设置文件保存到当前目录
        current_dir = os.getcwd()
        file_name = "物业资料报表.xlsx"
        file_path = os.path.join(current_dir, file_name)
        
        try:
            wb.save(file_path)
            
            # 自动打开Excel文件
            try:
                webbrowser.open(file_path)
                messagebox.showinfo("成功", f"物业资料已成功导出到：{file_path}\n并已自动打开，请查看。")
            except Exception as e:
                messagebox.showinfo("成功", f"物业资料已成功导出到：{file_path}\n自动打开文件失败：{str(e)}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败：{str(e)}")
    
    def import_property_data(self):
        """导入物业资料"""
        # 检查openpyxl库是否可用
        if not OPENPYXL_AVAILABLE:
            messagebox.showerror("错误", "请先安装openpyxl库：pip install openpyxl")
            return
        
        # 打开文件选择对话框
        file_path = filedialog.askopenfilename(
            title="选择物业资料Excel文件",
            filetypes=[("Excel files", "*.xlsx")]
        )
        
        if not file_path:
            return  # 用户取消选择
        
        try:
            # 打开Excel文件
            wb = openpyxl.load_workbook(file_path)
            ws = wb.active
            
            # 获取表头行，用于验证文件格式
            header_row = []
            for col in range(1, 8):  # 假设最多7列数据
                cell_value = ws.cell(row=2, column=col).value
                if cell_value:
                    header_row.append(cell_value)
            
            # 验证表头格式是否正确
            expected_headers = ["序号", "物业名称", "类型", "面积(㎡)", "联系人", "联系电话", "状态"]
            
            # 检查是否包含必需的表头
            required_headers = ["物业名称", "类型"]
            required_found = all(header in header_row for header in required_headers)
            
            if not required_found:
                messagebox.showerror("错误", "Excel文件格式不正确，缺少必需的列标题")
                return
            
            # 确认导入
            if not messagebox.askyesno("确认导入", "确定要导入物业资料吗？这将添加新的物业记录，但不会覆盖现有记录。"):
                return
            
            # 开始导入数据
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 查找各列的索引
            name_col = -1
            type_col = -1
            area_col = -1
            contact_col = -1
            phone_col = -1
            status_col = -1
            
            for i, header in enumerate(header_row):
                if "物业名称" in header:
                    name_col = i + 1  # Excel列索引从1开始
                elif "类型" in header:
                    type_col = i + 1
                elif "面积" in header:
                    area_col = i + 1
                elif "联系人" in header:
                    contact_col = i + 1
                elif "电话" in header:
                    phone_col = i + 1
                elif "状态" in header:
                    status_col = i + 1
            
            # 记录导入成功和失败的数量
            success_count = 0
            fail_count = 0
            fail_reasons = []
            
            # 从第3行开始读取数据（假设第1行是标题，第2行是表头）
            for row_idx in range(3, ws.max_row + 1):
                try:
                    # 获取物业名称（必需字段）
                    name = ws.cell(row=row_idx, column=name_col).value
                    if not name or name.strip() == '':
                        fail_count += 1
                        fail_reasons.append(f"第{row_idx}行：物业名称为空")
                        continue
                    
                    # 获取物业类型（必需字段）
                    property_type = ws.cell(row=row_idx, column=type_col).value
                    if not property_type or property_type.strip() == '':
                        fail_count += 1
                        fail_reasons.append(f"第{row_idx}行：物业类型为空")
                        continue
                    
                    # 获取面积（可选字段）
                    area = ws.cell(row=row_idx, column=area_col).value if area_col > 0 else 0
                    try:
                        area = float(area) if area else 0
                    except (ValueError, TypeError):
                        area = 0
                    
                    # 获取联系人（可选字段）
                    contact = ws.cell(row=row_idx, column=contact_col).value if contact_col > 0 else ''
                    contact = str(contact).strip() if contact is not None else ''
                    
                    # 获取联系电话（可选字段）
                    phone = ws.cell(row=row_idx, column=phone_col).value if phone_col > 0 else ''
                    phone = str(phone).strip() if phone is not None else ''
                    
                    # 获取状态（可选字段，默认为'正常'）
                    status = ws.cell(row=row_idx, column=status_col).value if status_col > 0 else '正常'
                    status = str(status).strip() if status is not None else '正常'
                    
                    # 检查物业名称是否已存在
                    cursor.execute("SELECT COUNT(*) FROM properties WHERE name = ?", (name,))
                    if cursor.fetchone()[0] > 0:
                        fail_count += 1
                        fail_reasons.append(f"第{row_idx}行：物业名称'{name}'已存在")
                        continue
                    
                    # 插入数据
                    cursor.execute(
                        "INSERT INTO properties (name, type, area, contact_person, contact_phone, status) VALUES (?, ?, ?, ?, ?, ?)",
                        (name, property_type, area, contact, phone, status)
                    )
                    success_count += 1
                except Exception as e:
                    fail_count += 1
                    fail_reasons.append(f"第{row_idx}行：导入失败 - {str(e)}")
            
            # 提交事务
            conn.commit()
            conn.close()
            
            # 刷新物业列表
            self.load_properties()
            
            # 显示导入结果
            result_msg = f"物业资料导入完成！\n成功导入：{success_count}条记录\n失败：{fail_count}条记录"
            
            if fail_reasons:
                result_msg += "\n\n失败详情：\n" + "\n".join(fail_reasons[:10])  # 只显示前10个失败原因
                if len(fail_reasons) > 10:
                    result_msg += f"\n... 还有{len(fail_reasons) - 10}条失败原因未显示"
            
            messagebox.showinfo("导入结果", result_msg)
        except Exception as e:
            messagebox.showerror("错误", f"导入物业资料失败：{str(e)}")
    
    def analyze_report(self):
        """生成报表分析图表"""
        # 检查matplotlib是否可用
        if not MATPLOTLIB_AVAILABLE:
            messagebox.showerror("错误", "请先安装matplotlib库：pip install matplotlib")
            return
        
        # 获取当前查询条件和数据
        month = self.report_month_combo.get()
        property_type = self.report_type_combo.get()
        property_str = self.report_property_combo.get()
        
        # 获取报表数据
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        
        # 构建查询SQL
        query = '''
            SELECT p.name, p.type,
                   strftime('%Y-%m', mr.reading_date) as month,
                   (mr.water_current - mr.water_previous + mr.water_adjustment) as water_usage,
                   mr.water_amount,
                   (mr.electricity_current - mr.electricity_previous + mr.electricity_adjustment) as electricity_usage,
                   mr.electricity_amount,
                   mr.total_amount
            FROM meter_readings mr
            JOIN properties p ON mr.property_id = p.id
        '''
        
        params = []
        where_clauses = []
        
        # 月份筛选逻辑
        if month and month != "全部":
            where_clauses.append("strftime('%Y-%m', mr.reading_date) = ?")
            params.append(month)
        
        if property_type != "全部":
            where_clauses.append("p.type = ?")
            params.append(property_type)
        
        # 添加物业名称筛选条件
        if property_str and property_str != "全部":
            property_id = property_str.split('-')[0]
            where_clauses.append("p.id = ?")
            params.append(property_id)
        
        if where_clauses:
            query += " WHERE " + " AND ".join(where_clauses)
        
        cursor.execute(query, params)
        rows = cursor.fetchall()
        conn.close()
        
        if not rows:
            messagebox.showinfo("提示", "没有数据可供分析")
            return
        
        # 创建分析窗口
        analysis_window = tk.Toplevel(self.root)
        analysis_window.title("报表分析")
        analysis_window.geometry("1000x700")
        
        # 创建Tab控件
        tab_control = ttk.Notebook(analysis_window)
        tab_control.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 创建不同类型的分析图表
        self.create_water_electricity_comparison_chart(tab_control, rows)
        self.create_property_comparison_chart(tab_control, rows)
        self.create_usage_amount_chart(tab_control, rows)
        self.create_monthly_trend_chart(tab_control, rows)
        
    def create_water_electricity_comparison_chart(self, tab_control, rows):
        """创建水电气费用对比图"""
        tab = ttk.Frame(tab_control)
        tab_control.add(tab, text="水电气费用对比")
        
        # 计算总水费、总电费
        total_water_amount = sum(row[4] for row in rows)
        total_electricity_amount = sum(row[6] for row in rows)
        
        # 创建图表
        fig, ax = plt.subplots(figsize=(10, 5))
        
        categories = ['水费', '电费']
        amounts = [total_water_amount, total_electricity_amount]
        
        ax.bar(categories, amounts, color=['#4CAF50', '#2196F3'])
        ax.set_title('水电气费用总览')
        ax.set_ylabel('金额 (元)')
        
        # 在柱子上方显示数值
        for i, v in enumerate(amounts):
            ax.text(i, v + 0.05 * max(amounts), f'{v:.2f}元', ha='center')
        
        # 创建Canvas并显示图表
        canvas = FigureCanvasTkAgg(fig, master=tab)
        canvas.draw()
        canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
        
        # 添加图表解读
        explanation = ttk.Label(tab, text=f"本图表展示了当前筛选条件下的水电气费用总览。\n" \
                              f"水费总额为{total_water_amount:.2f}元，电费总额为{total_electricity_amount:.2f}元。\n" \
                              f"可直观比较水电气费用占比，帮助了解整体费用结构。",
                              justify=tk.LEFT, wraplength=900)
        explanation.pack(pady=10, padx=10, anchor=tk.W)
        
        # 清理资源
        plt.close(fig)
    
    def create_property_comparison_chart(self, tab_control, rows):
        """创建各物业费用对比图"""
        tab = ttk.Frame(tab_control)
        tab_control.add(tab, text="各物业费用对比")
        
        # 按物业名称分组统计
        property_data = {}
        for row in rows:
            property_name = row[0]
            if property_name not in property_data:
                property_data[property_name] = {'water': 0, 'electricity': 0, 'total': 0}
            property_data[property_name]['water'] += row[4]
            property_data[property_name]['electricity'] += row[6]
            property_data[property_name]['total'] += row[7]
        
        # 创建图表
        fig, ax = plt.subplots(figsize=(12, 6))
        
        # 准备数据
        properties = list(property_data.keys())
        water_amounts = [property_data[p]['water'] for p in properties]
        electricity_amounts = [property_data[p]['electricity'] for p in properties]
        
        # 设置柱状图宽度
        width = 0.35
        x = range(len(properties))
        
        # 创建堆叠柱状图
        ax.bar(x, water_amounts, width, label='水费', color='#4CAF50')
        ax.bar(x, electricity_amounts, width, bottom=water_amounts, label='电费', color='#2196F3')
        
        # 设置图表属性
        ax.set_title('各物业水电气费用对比')
        ax.set_ylabel('金额 (元)')
        ax.set_xticks(x)
        ax.set_xticklabels(properties, rotation=45, ha='right')
        ax.legend()
        
        # 调整布局
        plt.tight_layout()
        
        # 创建Canvas并显示图表
        canvas = FigureCanvasTkAgg(fig, master=tab)
        canvas.draw()
        canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
        
        # 添加图表解读
        total_overall = sum(pd['total'] for pd in property_data.values())
        explanation = ttk.Label(tab, text=f"本图表展示了各物业的水电气费用对比。\n" \
                              f"总计费用{total_overall:.2f}元，可直观比较不同物业间的费用差异。\n" \
                              f"每个物业的堆叠柱状图显示了水费与电费的构成比例，帮助识别高耗能物业。",
                              justify=tk.LEFT, wraplength=900)
        explanation.pack(pady=10, padx=10, anchor=tk.W)
        
        # 清理资源
        plt.close(fig)
        
    def create_usage_amount_chart(self, tab_control, rows):
        """创建用量与金额关系图"""
        tab = ttk.Frame(tab_control)
        tab_control.add(tab, text="用量与金额关系")
        
        # 准备数据
        water_usages = [row[3] for row in rows]
        water_amounts = [row[4] for row in rows]
        electricity_usages = [row[5] for row in rows]
        electricity_amounts = [row[6] for row in rows]
        
        # 创建图表
        fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
        
        # 水费与用水量关系
        ax1.scatter(water_usages, water_amounts, color='#4CAF50', label='水费')
        ax1.set_title('水费与用水量关系')
        ax1.set_xlabel('用水量 (吨)')
        ax1.set_ylabel('金额 (元)')
        ax1.legend()
        ax1.grid(True)
        
        # 电费与用电量关系
        ax2.scatter(electricity_usages, electricity_amounts, color='#2196F3', label='电费')
        ax2.set_title('电费与用电量关系')
        ax2.set_xlabel('用电量 (度)')
        ax2.set_ylabel('金额 (元)')
        ax2.legend()
        ax2.grid(True)
        
        # 调整布局
        plt.tight_layout()
        
        # 创建Canvas并显示图表
        canvas = FigureCanvasTkAgg(fig, master=tab)
        canvas.draw()
        canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
        
        # 添加图表解读
        avg_water_rate = sum(wa/wu for wu, wa in zip(water_usages, water_amounts) if wu > 0) / len([wu for wu in water_usages if wu > 0]) if water_usages else 0
        avg_electricity_rate = sum(ea/eu for eu, ea in zip(electricity_usages, electricity_amounts) if eu > 0) / len([eu for eu in electricity_usages if eu > 0]) if electricity_usages else 0
        explanation = ttk.Label(tab, text=f"本图表展示了用水量与水费、用电量与电费之间的关系。\n" \
                              f"水费均价约{avg_water_rate:.2f}元/吨，电费均价约{avg_electricity_rate:.2f}元/度。\n" \
                              f"散点图可帮助识别用量与费用的异常点，分析收费标准执行情况。",
                              justify=tk.LEFT, wraplength=900)
        explanation.pack(pady=10, padx=10, anchor=tk.W)
        
        # 清理资源
        plt.close(fig)
        
    def create_monthly_trend_chart(self, tab_control, rows):
        """创建月度趋势图"""
        tab = ttk.Frame(tab_control)
        tab_control.add(tab, text="月度趋势")
        
        # 按月份分组统计
        monthly_data = {}
        for row in rows:
            month = row[2]
            if month not in monthly_data:
                monthly_data[month] = {'water': 0, 'electricity': 0, 'total': 0}
            monthly_data[month]['water'] += row[4]
            monthly_data[month]['electricity'] += row[6]
            monthly_data[month]['total'] += row[7]
        
        # 按月份排序
        sorted_months = sorted(monthly_data.keys())
        
        # 准备数据
        months = sorted_months
        water_amounts = [monthly_data[m]['water'] for m in months]
        electricity_amounts = [monthly_data[m]['electricity'] for m in months]
        total_amounts = [monthly_data[m]['total'] for m in months]
        
        # 创建图表
        fig, ax = plt.subplots(figsize=(12, 6))
        
        # 创建折线图
        ax.plot(months, water_amounts, marker='o', label='水费', color='#4CAF50')
        ax.plot(months, electricity_amounts, marker='s', label='电费', color='#2196F3')
        ax.plot(months, total_amounts, marker='^', label='总金额', color='#FF9800')
        
        # 设置图表属性
        ax.set_title('月度费用趋势')
        ax.set_ylabel('金额 (元)')
        ax.set_xticks(range(len(months)))
        ax.set_xticklabels(months, rotation=45, ha='right')
        ax.legend()
        ax.grid(True)
        
        # 调整布局
        plt.tight_layout()
        
        # 创建Canvas并显示图表
        canvas = FigureCanvasTkAgg(fig, master=tab)
        canvas.draw()
        canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
        
        # 添加图表解读
        trend_direction = "上升" if len(total_amounts) > 1 and total_amounts[-1] > total_amounts[0] else "下降" if len(total_amounts) > 1 else "稳定"
        explanation = ttk.Label(tab, text=f"本图表展示了{len(months)}个月份的水电气费用趋势变化。\n" \
                              f"整体费用呈{trend_direction}趋势，可清晰识别季节性波动和长期变化规律。\n" \
                              f"水费、电费和总金额三条曲线的交叉和间距变化，反映了不同费用类型的变化特征。",
                              justify=tk.LEFT, wraplength=900)
        explanation.pack(pady=10, padx=10, anchor=tk.W)
        
        # 清理资源
        plt.close(fig)

    def export_excel(self):
        """导出Excel"""
        # 检查openpyxl库是否可用
        if not OPENPYXL_AVAILABLE:
            messagebox.showerror("错误", "请先安装openpyxl库：pip install openpyxl")
            return
        
        # 获取当前选择的月份、物业类型和物业名称
        month = self.report_month_combo.get()
        property_type = self.report_type_combo.get()
        property_str = self.report_property_combo.get()
        
        if not month:
            messagebox.showerror("错误", "请先选择月份")
            return
        
        # 构建查询条件获取数据
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        
        # 构建查询SQL，包含状态信息（是否已收款）
        query = '''
            SELECT p.name, p.type, 
                   strftime('%Y-%m', mr.reading_date) as month,
                   mr.water_previous || '→' || mr.water_current as water_reading,
                   (mr.water_current - mr.water_previous + mr.water_adjustment) as water_usage,
                   mr.water_amount,
                   mr.electricity_previous || '→' || mr.electricity_current as electricity_reading,
                   (mr.electricity_current - mr.electricity_previous + mr.electricity_adjustment) as electricity_usage,
                   mr.electricity_amount,
                   mr.total_amount,
                   mr.reading_date,
                   CASE WHEN pm.id IS NOT NULL AND pm.status = '已付款' THEN '已收款' ELSE '未收款' END as status
            FROM meter_readings mr
            JOIN properties p ON mr.property_id = p.id
            LEFT JOIN payments pm ON mr.property_id = pm.property_id AND strftime('%Y-%m', mr.reading_date) = strftime('%Y-%m', pm.billing_date)
        '''
        params = []
        where_clauses = []
        
        # 月份筛选逻辑，如果选择了"全部"则不添加月份条件
        if month and month != "全部":
            where_clauses.append("strftime('%Y-%m', mr.reading_date) = ?")
            params.append(month)
        
        if property_type != "全部":
            where_clauses.append("p.type = ?")
            params.append(property_type)
        
        # 添加物业名称筛选条件
        if property_str and property_str != "全部":
            property_id = property_str.split('-')[0]
            where_clauses.append("p.id = ?")
            params.append(property_id)
        
        if where_clauses:
            query += " WHERE " + " AND ".join(where_clauses)
        
        cursor.execute(query, params)
        rows = cursor.fetchall()
        conn.close()
        
        if not rows:
            messagebox.showinfo("提示", "没有数据可导出")
            return
        
        # 创建Excel工作簿
        wb = openpyxl.Workbook()
        ws = wb.active
        # 如果选择了全部月份，标题显示为"全部月份水电费报表"
        if month == "全部":
            ws.title = "全部月份水电费报表"
        else:
            ws.title = f"{month}水电费报表"
        
        # 设置表头样式：背景色、加粗、居中、边框
        header_fill = PatternFill(start_color='DDEBF7', end_color='DDEBF7', fill_type='solid')
        header_font = Font(bold=True)
        header_alignment = Alignment(horizontal='center', vertical='center')
        
        # 设置边框样式
        thin_border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        
        # 插入表格标题行
        title = f"{month if month != '全部' else '全部月份'}水电费报表"
        title_cell = ws.cell(row=1, column=1)
        title_cell.value = title
        # 合并标题单元格到第13列(M列)
        ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=13)
        # 设置标题样式：加粗、居中、字体大小12
        title_cell.font = Font(bold=True, size=12)
        title_cell.alignment = Alignment(horizontal='center', vertical='center')
        
        # 设置表头（在第2行），并在首列添加"序号"列
        headers = ["序号", "状态", "物业名称", "类型", "月份", "水表读数", "水用量(吨)", "水费(元)", "电表读数", "电用量(度)", "电费(元)", "总金额(元)", "抄表日期"]
        for col_idx, header in enumerate(headers, 1):
            cell = ws.cell(row=2, column=col_idx)
            cell.value = header
            cell.font = header_font
            cell.alignment = header_alignment
            cell.fill = header_fill
            cell.border = thin_border
        
        # 填充数据并设置边框
        total_amount = 0
        for row_idx, row_data in enumerate(rows, 3):
            # 添加序号
            cell = ws.cell(row=row_idx, column=1)
            cell.value = row_idx - 2  # 序号从1开始
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = thin_border
            # 状态（是否已收款）
            cell = ws.cell(row=row_idx, column=2)
            cell.value = row_data[11] if len(row_data) > 11 else '未收款'
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = thin_border
            # 物业名称
            cell = ws.cell(row=row_idx, column=3)
            cell.value = row_data[0] if len(row_data) > 0 else ''
            cell.border = thin_border
            # 类型
            cell = ws.cell(row=row_idx, column=4)
            cell.value = row_data[1] if len(row_data) > 1 else ''
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = thin_border
            # 月份
            cell = ws.cell(row=row_idx, column=5)
            cell.value = row_data[2] if len(row_data) > 2 else ''
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = thin_border
            # 水表读数
            cell = ws.cell(row=row_idx, column=6)
            cell.value = row_data[3] if len(row_data) > 3 else ''
            cell.alignment = Alignment(horizontal='right', vertical='center')
            cell.border = thin_border
            # 水用量
            cell = ws.cell(row=row_idx, column=7)
            cell.value = row_data[4] if len(row_data) > 4 else 0
            cell.number_format = '0.0'
            cell.alignment = Alignment(horizontal='right', vertical='center')
            cell.border = thin_border
            # 水费（四舍五入到元）
            cell = ws.cell(row=row_idx, column=8)
            water_fee = row_data[5] if len(row_data) > 5 else 0
            cell.value = round(water_fee) if isinstance(water_fee, (int, float)) else 0
            cell.number_format = '0'
            cell.alignment = Alignment(horizontal='right', vertical='center')
            cell.border = thin_border
            # 电表读数
            cell = ws.cell(row=row_idx, column=9)
            cell.value = row_data[6] if len(row_data) > 6 else ''
            cell.alignment = Alignment(horizontal='right', vertical='center')
            cell.border = thin_border
            # 电用量
            cell = ws.cell(row=row_idx, column=10)
            cell.value = row_data[7] if len(row_data) > 7 else 0
            cell.number_format = '0.0'
            cell.alignment = Alignment(horizontal='right', vertical='center')
            cell.border = thin_border
            # 电费（四舍五入到元）
            cell = ws.cell(row=row_idx, column=11)
            electric_fee = row_data[8] if len(row_data) > 8 else 0
            cell.value = round(electric_fee) if isinstance(electric_fee, (int, float)) else 0
            cell.number_format = '0'
            cell.alignment = Alignment(horizontal='right', vertical='center')
            cell.border = thin_border
            # 总金额（四舍五入到元）
            cell = ws.cell(row=row_idx, column=12)
            total = row_data[9] if len(row_data) > 9 else 0
            cell.value = round(total) if isinstance(total, (int, float)) else 0
            cell.number_format = '0'
            cell.alignment = Alignment(horizontal='right', vertical='center')
            cell.border = thin_border
            # 抄表日期
            cell = ws.cell(row=row_idx, column=13)
            cell.value = row_data[10] if len(row_data) > 10 else ''
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = thin_border
            
            # 累加总金额（四舍五入到元后累加）
            if len(row_data) > 9 and isinstance(row_data[9], (int, float)):
                total_amount += round(row_data[9])
        
        # 添加统计行
        stat_row = len(rows) + 4
        # 合并统计行单元格
        ws.merge_cells(start_row=stat_row, start_column=1, end_row=stat_row, end_column=13)
        # 设置统计信息（总金额四舍五入到元）
        stat_cell = ws.cell(row=stat_row, column=1)
        stat_cell.value = f"统计信息：共{len(rows)}条记录，总金额：{int(round(total_amount))}元"
        stat_cell.font = Font(bold=True)
        stat_cell.alignment = Alignment(horizontal='left', vertical='center')
        stat_cell.border = thin_border
        
        # 优化列宽，为不同类型的列设置合适的宽度
        column_widths = [8, 10, 20, 10, 10, 12, 12, 12, 12, 12, 12, 12, 15]  # 序号、状态、物业名称等列宽
        for col_idx, width in enumerate(column_widths, 1):
            ws.column_dimensions[openpyxl.utils.get_column_letter(col_idx)].width = width
        
        # 设置文件保存到当前目录
        current_dir = os.getcwd()
        # 如果选择了具体的物业名称，将其添加到文件名中
        file_name = f"{month}水电费报表_{property_type}"
        if property_str and property_str != "全部":
            property_name = property_str.split('-')[1] if '-' in property_str else property_str
            file_name += f"_{property_name}"
        file_name += ".xlsx"
        file_path = os.path.join(current_dir, file_name)
        
        try:
            wb.save(file_path)
            
            # 自动打开Excel文件
            try:
                webbrowser.open(file_path)
                messagebox.showinfo("成功", f"Excel文件已成功导出到：{file_path}\n并已自动打开，请查看。")
            except Exception as e:
                messagebox.showinfo("成功", f"Excel文件已成功导出到：{file_path}\n自动打开文件失败：{str(e)}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败：{str(e)}")
    
    # === 收款管理方法 ===
    def load_bills(self):
        """加载待收款账单"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute('''
            SELECT pm.id, p.name, strftime('%Y-%m', pm.billing_date), pm.amount, pm.status, pm.billing_date
            FROM payments pm
            LEFT JOIN properties p ON pm.property_id = p.id
            WHERE pm.status = '待付款'
            ORDER BY strftime('%Y-%m', pm.billing_date) DESC, p.name ASC
        ''')
        rows = cursor.fetchall()
        conn.close()
        
        # 清空表格
        for item in self.bills_tree.get_children():
            self.bills_tree.delete(item)
        
        # 插入数据，处理可能为空的物业名称和状态显示，并添加序号
        for index, row in enumerate(rows, start=1):
            # 如果物业名称为空，显示"未知物业"
            if row[1] is None:
                row = list(row)
                row[1] = "未知物业"
            else:
                row = list(row)
            
            # 将数据库中的"待付款"状态显示为"未收款"
            if row[4] == "待付款":
                row[4] = "未收款"
            
            # 将总金额四舍五入为整数
            try:
                row[3] = str(round(float(row[3]))) if row[3] is not None else "0"
            except (ValueError, TypeError):
                pass
            
            # 在ID列后插入序号
            row.insert(1, str(index))
            
            self.bills_tree.insert("", tk.END, values=tuple(row))
    
    def load_payments(self):
        """加载收款记录"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        cursor.execute('''
            SELECT p.name, strftime('%Y-%m', pm.billing_date), pm.amount, pm.payer, pm.payment_date, '系统'
            FROM payments pm
            JOIN properties p ON pm.property_id = p.id
            WHERE pm.status = '已付款'
            ORDER BY strftime('%Y-%m', pm.billing_date) DESC, p.name ASC
        ''')
        rows = cursor.fetchall()
        conn.close()
        
        # 清空表格
        for item in self.payments_tree.get_children():
            self.payments_tree.delete(item)
        
        # 计算总金额
        total_amount = 0
        # 插入数据
        for index, row in enumerate(rows, start=1):
            # 转换为列表以便修改
            row_list = list(row)
            # 将实收金额四舍五入为整数
            try:
                row_list[2] = str(round(float(row_list[2]))) if row_list[2] is not None else "0"
            except (ValueError, TypeError):
                pass
            # 在首列前方插入序号
            row_list.insert(0, str(index))
            self.payments_tree.insert("", tk.END, values=tuple(row_list))
            # 累加金额（因为插入了序号列，所以索引需要+1）
            try:
                total_amount += float(row[2]) if row[2] is not None else 0
            except (ValueError, TypeError):
                pass
        
        # 更新记录总条数和实收金额总和标签
        record_count = len(rows)
        self.total_amount_label.config(text=f"共{record_count}条记录，总金额：{round(total_amount)}元")
    
    def on_bill_select(self, event):
        """账单选择事件处理"""
        selection = self.bills_tree.selection()
        if not selection:
            return
        
        item = self.bills_tree.item(selection[0])
        bill_id = item['values'][0]  # 获取账单ID
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 查询该账单对应的物业ID
            cursor.execute('SELECT property_id FROM payments WHERE id=?', (bill_id,))
            result = cursor.fetchone()
            if result:
                property_id = result[0]
                
                # 查询该物业的联系人信息
                cursor.execute('SELECT contact_person FROM properties WHERE id=?', (property_id,))
                contact_result = cursor.fetchone()
                if contact_result and contact_result[0]:
                    # 设置缴费人默认值为物业联系人
                    self.payer_entry.delete(0, tk.END)
                    self.payer_entry.insert(0, contact_result[0])
            
            conn.close()
        except Exception as e:
            print(f"获取联系人信息失败: {str(e)}")
            
    def mark_paid(self):
        """标记已收款（支持批量操作）"""
        selection = self.bills_tree.selection()
        if not selection:
            messagebox.showerror("错误", "请选择要标记的账单！")
            return
        
        payer = self.payer_entry.get().strip()
        payment_date = self.payment_date_entry.get().strip()
        notes = self.payment_notes_entry.get().strip()
        
        # 验证必填信息
        if not payer:
            messagebox.showerror("错误", "请输入缴费人！")
            return
        
        # 验证日期格式
        try:
            datetime.strptime(payment_date, "%Y-%m-%d")
        except ValueError:
            messagebox.showerror("错误", "请输入正确的日期格式 (YYYY-MM-DD)！")
            return
        
        # 准备批量更新
        bill_ids = []
        skipped_count = 0
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 检查所有选中记录的状态
            for item_id in selection:
                item = self.bills_tree.item(item_id)
                bill_id = item['values'][0]
                current_status = item['values'][4]  # 获取当前显示状态
                
                # 检查账单是否已经是已收款状态
                if current_status == '已收款':
                    skipped_count += 1
                    continue
                
                # 再次检查数据库中的状态，避免并发问题
                cursor.execute('SELECT status FROM payments WHERE id=?', (bill_id,))
                result = cursor.fetchone()
                
                # 检查结果是否为空
                if not result:
                    skipped_count += 1
                    continue
                
                db_status = result[0]
                if db_status == '已付款':
                    skipped_count += 1
                    continue
                
                bill_ids.append(bill_id)
            
            # 执行批量更新
            if bill_ids:
                # 构建批量更新的参数列表
                params = [(payer, payment_date, notes, bill_id) for bill_id in bill_ids]
                
                # 执行批量更新
                cursor.executemany('''
                    UPDATE payments 
                    SET status='已付款', payer=?, payment_date=?, notes=?
                    WHERE id=?
                ''', params)
                conn.commit()
            
            conn.close()
            
            # 显示操作结果
            updated_count = len(bill_ids)
            if updated_count == 0:
                messagebox.showinfo("提示", "没有记录被更新！")
            else:
                message = f"成功更新了{updated_count}条账单的收款状态！"
                if skipped_count > 0:
                    message += f"\n跳过了{skipped_count}条已收款或不存在的记录。"
                messagebox.showinfo("成功", message)
            
            # 刷新列表
            self.load_bills()
            self.load_payments()
            
            # 清空表单
            self.payer_entry.delete(0, tk.END)
            self.payment_notes_entry.delete(0, tk.END)
            
        except sqlite3.IntegrityError:
            messagebox.showerror("错误", "数据完整性错误，请检查输入数据！")
        except sqlite3.OperationalError:
            messagebox.showerror("错误", "数据库操作错误，请稍后再试！")
        except Exception as e:
            messagebox.showerror("错误", f"更新失败: {str(e)}")
            
    def delete_payment_record(self):
        """删除收款记录，将已收款记录改回未收款状态"""
        selection = self.payments_tree.selection()
        if not selection:
            messagebox.showerror("错误", "请选择要删除的收款记录！")
            return
        
        # 验证密码
        if not self.verify_password("删除收款记录"):
            messagebox.showerror("权限不足", "您需要输入密码才能删除收款记录！")
            return
        
        item = self.payments_tree.item(selection[0])
        record_data = item['values']
        
        # 从收款记录中获取物业名称和账单月份
        property_name = record_data[1]
        billing_month = record_data[2]
        
        try:
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 查找对应物业ID
            cursor.execute('SELECT id FROM properties WHERE name=?', (property_name,))
            property_result = cursor.fetchone()
            
            if not property_result:
                conn.close()
                messagebox.showerror("错误", f"未找到物业 '{property_name}' 的信息！")
                return
            
            property_id = property_result[0]
            
            # 查找对应已付款记录
            cursor.execute('''
                SELECT id, status FROM payments 
                WHERE property_id=? 
                AND strftime('%Y-%m', billing_date)=?
                AND status='已付款'
            ''', (property_id, billing_month))
            
            payment_result = cursor.fetchone()
            if not payment_result:
                conn.close()
                messagebox.showerror("错误", f"未找到 '{property_name}' {billing_month} 月份的已付款记录！")
                return
            
            payment_id = payment_result[0]
            
            # 将状态改回待付款，并清除付款信息
            cursor.execute('''
                UPDATE payments 
                SET status='待付款', payer=NULL, payment_date=NULL, notes=NULL
                WHERE id=?
            ''', (payment_id,))
            
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", "收款记录已删除，该记录已移回待收款账单列表！")
            self.load_bills()
            self.load_payments()
            
        except sqlite3.IntegrityError:
            messagebox.showerror("错误", "数据完整性错误，请检查输入数据！")
        except sqlite3.OperationalError:
            messagebox.showerror("错误", "数据库操作错误，请稍后再试！")
        except Exception as e:
            messagebox.showerror("错误", f"删除失败: {str(e)}")

    def init_payment_filters(self):
        """初始化收款记录筛选下拉框"""
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        
        # 获取所有物业名称
        cursor.execute("SELECT id, name FROM properties")
        properties = cursor.fetchall()
        
        # 获取所有账单月份
        cursor.execute("SELECT DISTINCT strftime('%Y-%m', billing_date) FROM payments WHERE status = '已付款' ORDER BY billing_date DESC")
        months = [row[0] for row in cursor.fetchall()]
        
        conn.close()
        
        # 更新物业下拉框，添加"全部"选项
        self.payment_property_combo['values'] = ["全部"] + [p[1] for p in properties]
        if properties:
            self.payment_property_combo.current(0)  # 默认选择"全部"
        
        # 更新月份下拉框，添加"全部"选项
        if not months:
            # 如果没有数据，使用最近12个月作为默认值
            current = datetime.now()
            months = []
            for i in range(12):
                month = current - timedelta(days=30*i)
                months.append(month.strftime("%Y-%m"))
        
        self.payment_month_combo['values'] = ["全部"] + months
        if months:
            self.payment_month_combo.current(0)  # 默认选择"全部"
    
    def filter_payments(self):
        """根据筛选条件过滤收款记录"""
        selected_month = self.payment_month_combo.get()
        selected_property = self.payment_property_combo.get()
        
        conn = sqlite3.connect('water_electricity.db')
        cursor = conn.cursor()
        
        query = '''
            SELECT p.name, strftime('%Y-%m', pm.billing_date), pm.amount, pm.payer, pm.payment_date, '系统'
            FROM payments pm
            JOIN properties p ON pm.property_id = p.id
            WHERE pm.status = '已付款'
        '''
        
        params = []
        
        # 添加月份筛选条件
        if selected_month and selected_month != "全部":
            query += " AND strftime('%Y-%m', pm.billing_date) = ?"
            params.append(selected_month)
        
        # 添加物业名称筛选条件
        if selected_property and selected_property != "全部":
            query += " AND p.name = ?"
            params.append(selected_property)
        
        # 添加排序
        query += " ORDER BY strftime('%Y-%m', pm.billing_date) DESC, p.name ASC"
        
        cursor.execute(query, params)
        rows = cursor.fetchall()
        conn.close()
        
        # 清空表格
        for item in self.payments_tree.get_children():
            self.payments_tree.delete(item)
        
        # 计算总金额
        total_amount = 0
        # 插入数据
        for index, row in enumerate(rows, start=1):
            # 转换为列表以便修改
            row_list = list(row)
            # 在首列前方插入序号
            row_list.insert(0, str(index))
            self.payments_tree.insert("", tk.END, values=tuple(row_list))
            # 累加金额（因为插入了序号列，所以索引需要+1）
            try:
                total_amount += float(row[2]) if row[2] is not None else 0
            except (ValueError, TypeError):
                pass
        
        # 更新记录总条数和实收金额总和标签
        record_count = len(rows)
        self.total_amount_label.config(text=f"共{record_count}条记录，总金额：{round(total_amount)}元")
        
        messagebox.showinfo("筛选结果", f"找到 {len(rows)} 条收款记录")
    
    def reset_filters(self):
        """重置筛选条件"""
        self.payment_month_combo.current(0)  # 重置为"全部"
        self.payment_property_combo.current(0)  # 重置为"全部"
        self.load_payments()  # 重新加载所有收款记录
    
    def import_reading_data(self):
        """导入抄表数据功能"""
        # 检查openpyxl库是否可用
        if not OPENPYXL_AVAILABLE:
            messagebox.showerror("错误", "未安装openpyxl库，请先安装: pip install openpyxl")
            return
        
        try:
            # 1. 支持手动选择抄表单对应的目录路径
            directory = filedialog.askdirectory(title="选择存放抄表单的目录")
            if not directory:
                messagebox.showinfo("提示", "未选择目录，取消导入操作")
                return
            
            # 2. 提供待导入Excel数据文件的选择功能
            file_path = filedialog.askopenfilename(
                title="选择待导入的Excel文件",
                filetypes=[("Excel文件", "*.xlsx")],
                initialdir=directory
            )
            
            if not file_path:
                messagebox.showinfo("提示", "未选择文件，取消导入操作")
                return
            
            # 获取抄表月份
            # 假设文件名格式为"2025-09水电费抄单.xlsx"，提取2025-09作为抄表月份
            file_name = os.path.basename(file_path)
            reading_month = file_name[:7]  # 假设文件名以"YYYY-MM"开头
            
            try:
                # 验证月份格式是否正确
                datetime.strptime(reading_month, "%Y-%m")
            except ValueError:
                # 如果文件名不是预期格式，提示用户手动选择月份
                selected_month = self.reading_month_combo.get()
                if not selected_month or selected_month == "全部":
                    messagebox.showerror("错误", "无法从文件名提取月份，请先在界面上选择抄表月份")
                    return
                reading_month = selected_month
            
            # 3. 从选定Excel文件中提取数据
            wb = openpyxl.load_workbook(file_path)
            ws = wb.active
            
            # 读取数据（跳过标题行，从第4行开始）
            imported_data = []
            for row_idx in range(4, ws.max_row + 1):
                # 检查是否为空行
                property_name_cell = ws[f'B{row_idx}']
                if not property_name_cell.value:
                    continue
                
                data = {
                    'property_name': property_name_cell.value,
                    'water_previous': ws[f'C{row_idx}'].value or 0,
                    'water_current': ws[f'D{row_idx}'].value or 0,
                    'electricity_previous': ws[f'E{row_idx}'].value or 0,
                    'electricity_current': ws[f'F{row_idx}'].value or 0,
                    'remark': ws[f'G{row_idx}'].value or ""
                }
                imported_data.append(data)
            
            if not imported_data:
                messagebox.showinfo("提示", "未找到可导入的数据")
                return
            
            # 连接数据库
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            processed_count = 0
            skipped_count = 0
            
            # 4. 处理导入的数据
            for data in imported_data:
                # 获取物业ID
                cursor.execute("SELECT id, type FROM properties WHERE name=?", (data['property_name'],))
                property_result = cursor.fetchone()
                
                if not property_result:
                    skipped_count += 1
                    continue  # 跳过未找到的物业
                
                property_id, property_type = property_result
                
                # 获取最新的收费标准
                cursor.execute("SELECT water_price, electricity_price FROM price_config WHERE id=(SELECT MAX(id) FROM price_config WHERE property_type=?)", (property_type,))
                price_result = cursor.fetchone()
                
                if not price_result:
                    skipped_count += 1
                    continue  # 跳过未找到收费标准的物业
                
                water_price, electricity_price = price_result
                
                # 计算费用
                try:
                    water_prev = float(data['water_previous'])
                    water_curr = float(data['water_current'])
                    water_adj = 0.0  # 默认为0
                    
                    elec_prev = float(data['electricity_previous'])
                    elec_curr = float(data['electricity_current'])
                    elec_adj = 0.0  # 默认为0
                    
                    # 计算用量和费用
                    water_usage = water_curr - water_prev + water_adj
                    electricity_usage = elec_curr - elec_prev + elec_adj
                    
                    # 计算金额（四舍五入到元）
                    water_amount = self.round_to_nearest(water_usage * water_price)
                    electricity_amount = self.round_to_nearest(electricity_usage * electricity_price)
                    total_amount = self.round_to_nearest(water_amount + electricity_amount)
                    
                    # 检查是否已存在该月记录
                    reading_date = reading_month + "-01"
                    cursor.execute('''
                        SELECT id FROM meter_readings 
                        WHERE property_id=? AND strftime('%Y-%m', reading_date)=?
                    ''', (property_id, reading_month))
                    
                    existing_id = cursor.fetchone()
                    
                    if existing_id:
                        # 更新现有记录
                        cursor.execute('''
                            UPDATE meter_readings 
                            SET water_previous=?, water_current=?, electricity_previous=?, 
                                electricity_current=?, water_adjustment=?, electricity_adjustment=?, 
                                water_amount=?, electricity_amount=?, total_amount=?
                            WHERE id=?
                        ''', (water_prev, water_curr, elec_prev, 
                              elec_curr, water_adj, elec_adj, water_amount, electricity_amount, total_amount, existing_id[0]))
                    else:
                        # 插入新记录
                        cursor.execute('''
                            INSERT INTO meter_readings 
                            (property_id, reading_date, water_previous, water_current, electricity_previous, 
                             electricity_current, water_adjustment, electricity_adjustment, 
                             water_amount, electricity_amount, total_amount)
                            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                        ''', (property_id, reading_date, water_prev, water_curr, elec_prev, 
                              elec_curr, water_adj, elec_adj, water_amount, electricity_amount, total_amount))
                    
                    processed_count += 1
                    
                except ValueError:
                    skipped_count += 1
                    continue
            
            conn.commit()
            conn.close()
            
            # 5. 实时自动更新抄表明细记录列表的显示内容
            self.load_reading_history()
            
            # 显示导入结果
            messagebox.showinfo("导入完成", 
                               f"成功导入 {processed_count} 条记录，\n" 
                               f"跳过 {skipped_count} 条记录（可能是物业不存在或数据格式错误）")
            
        except Exception as e:
            messagebox.showerror("导入错误", f"导入抄表数据时发生错误：{str(e)}")
            import traceback
            traceback.print_exc()
    
    def generate_reading_form(self):
        """生成水电费抄表单"""
        # 1. 检查月份是否为"全部"或空值
        reading_month = self.reading_month_combo.get()
        if not reading_month or reading_month == "全部":
            messagebox.showerror("错误", "你是要生成月度水电费抄表单，月份值不能选择'全部'或者空！")
            return
        
        # 检查openpyxl库是否可用
        if not OPENPYXL_AVAILABLE:
            messagebox.showerror("错误", "请先安装openpyxl库以支持Excel文件生成功能！")
            return
        
        try:
            # 计算下一月份
            current_date = datetime.strptime(reading_month + "-01", "%Y-%m-%d")
            # 计算下一个月（处理12月的情况）
            if current_date.month == 12:
                next_month = f"{current_date.year + 1}-01"
            else:
                next_month = f"{current_date.year}-{current_date.month + 1:02d}"
            
            # 2. 创建Excel文件，文件命名格式为"抄表月份值的下一月份+水电费抄单.xlsx"
            file_name = f"{next_month}水电费抄单.xlsx"
            file_path = os.path.join(os.getcwd(), file_name)
            
            # 创建工作簿和工作表
            wb = openpyxl.Workbook()
            ws = wb.active
            ws.title = "水电费抄单"
            
            # 3. 生成表格样式和内容
            # A. A1单元格为表格标题，合并居中至表格末列
            title = f"{next_month}水电费抄表单"
            ws.merge_cells('A1:G1')  # 合并A1到G1单元格
            ws['A1'].value = title
            ws['A1'].font = Font(name='微软雅黑', size=16, bold=True)
            ws['A1'].alignment = Alignment(horizontal='center', vertical='center')
            
            # B. A2单元格输入"日期："，B2单元格输入当前日期
            ws['A2'].value = "日期："
            ws['B2'].value = datetime.now().strftime("%Y-%m-%d")
            ws['D2'].value = "本月总水表读数："
            ws['E2'].value = ""
            
            # 设置第二行字体和对齐方式
            for cell in ['A2', 'D2']:
                ws[cell].font = Font(name='微软雅黑', size=10, bold=True)
            for cell in ['B2', 'E2']:
                ws[cell].font = Font(name='微软雅黑', size=10)
            
            # 4. 第三行为表格标题行
            headers = ["序号", "物业名称", "上月水表读数", "本月水表读数", "上月电表读数", "本月电表读数", "备注"]
            for col_idx, header in enumerate(headers, 1):
                col_letter = openpyxl.utils.get_column_letter(col_idx)
                ws[f'{col_letter}3'].value = header
                ws[f'{col_letter}3'].font = Font(name='微软雅黑', size=10, bold=True)
                ws[f'{col_letter}3'].alignment = Alignment(horizontal='center', vertical='center')
                # 设置列宽
                ws.column_dimensions[col_letter].width = 15
            
            # 5. 提取抄表月份的水表本月读数和电表本月读数
            # 从数据库获取所有物业信息和抄表月份的数据
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 获取所有物业信息
            cursor.execute("SELECT id, name FROM properties")
            properties = cursor.fetchall()
            
            # 初始化行号
            row_num = 4
            
            # 初始化总水表读数
            total_water_reading = 0
            
            for idx, (property_id, property_name) in enumerate(properties, 1):
                # 查询抄表月份的抄表数据（作为下月的上月数据）
                cursor.execute('''
                    SELECT water_current, electricity_current 
                    FROM meter_readings 
                    WHERE property_id=? AND strftime('%Y-%m', reading_date)=?
                ''', (property_id, reading_month))
                
                result = cursor.fetchone()
                
                # 填充数据到表格
                ws[f'A{row_num}'].value = idx  # 序号
                ws[f'B{row_num}'].value = property_name  # 物业名称
                
                if result:
                    ws[f'C{row_num}'].value = result[0]  # 上月水表读数
                    ws[f'E{row_num}'].value = result[1]  # 上月电表读数
                    total_water_reading += result[0]  # 累加总水表读数
                else:
                    ws[f'C{row_num}'].value = ""  # 上月水表读数（空）
                    ws[f'E{row_num}'].value = ""  # 上月电表读数（空）
                    ws[f'G{row_num}'].value = ""  # 备注
                
                # 设置数值格式
                for col in ['C', 'D', 'E', 'F']:
                    ws[f'{col}{row_num}'].alignment = Alignment(horizontal='right')
                
                row_num += 1
            
            conn.close()
            
            # 填写本月总水表读数
            # ws['E2'].value = total_water_reading
            ws['E2'].value = ""
            # 6. 优化美化表格样式
            # 设置所有单元格的字体
            for row in ws.iter_rows(min_row=1, max_row=row_num-1, min_col=1, max_col=7):
                for cell in row:
                    if cell.font.name != '微软雅黑':  # 不覆盖已经设置的字体
                        cell.font = Font(name='微软雅黑', size=10)
                    
            # 添加边框
            from openpyxl.styles import Border, Side
            thin_border = Border(
                left=Side(style='thin'),
                right=Side(style='thin'),
                top=Side(style='thin'),
                bottom=Side(style='thin')
            )
            
            for row in ws.iter_rows(min_row=1, max_row=row_num-1, min_col=1, max_col=7):
                for cell in row:
                    cell.border = thin_border
            
            # 设置行高
            for i in range(1, row_num):
                ws.row_dimensions[i].height = 20
            
            # 7. 保存文件并自动打开
            wb.save(file_path)
            
            # 自动打开文件（Windows系统）
            if os.name == 'nt':  # Windows系统
                os.startfile(file_path)
            elif os.name == 'posix':  # macOS或Linux
                import subprocess
                try:
                    subprocess.run(['open', file_path], check=True)  # macOS
                except FileNotFoundError:
                    subprocess.run(['xdg-open', file_path], check=True)  # Linux
            
            messagebox.showinfo("成功", f"抄表单已生成并打开：{file_path}")
            
        except Exception as e:
            messagebox.showerror("错误", f"生成抄表单失败：{str(e)}")
    
    def backup_database(self):
        """备份数据库功能"""
        try:
            # 获取当前时间作为备份文件的一部分
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            default_filename = f"water_electricity_backup_{timestamp}.db"
            
            # 让用户选择保存位置
            file_path = filedialog.asksaveasfilename(
                title="保存数据库备份",
                defaultextension=".db",
                filetypes=[("数据库文件", "*.db")],
                initialfile=default_filename
            )
            
            if not file_path:
                return  # 用户取消了操作
            
            # 确保文件有.db后缀
            if not file_path.endswith('.db'):
                file_path += '.db'
            
            # 复制数据库文件
            import shutil
            shutil.copy2('water_electricity.db', file_path)
            
            messagebox.showinfo("成功", f"数据库备份成功！\n备份文件保存至：\n{file_path}")
            
        except Exception as e:
            messagebox.showerror("错误", f"数据库备份失败：{str(e)}")
    
    def restore_database(self):
        """恢复数据库功能"""
        try:
            # 让用户选择备份文件
            file_path = filedialog.askopenfilename(
                title="选择数据库备份文件",
                filetypes=[("数据库文件", "*.db")]
            )
            
            if not file_path:
                return  # 用户取消了操作
            
            # 确认恢复操作
            if not messagebox.askyesno("确认", "警告：恢复数据库将替换当前所有数据！\n确定要继续吗？"):
                return
            
            # 尝试关闭数据库连接（如果有的话）
            try:
                conn = sqlite3.connect('water_electricity.db')
                conn.close()
            except:
                pass  # 如果连接不存在或无法关闭，忽略错误
            
            # 复制备份文件到当前数据库文件
            import shutil
            shutil.copy2(file_path, 'water_electricity.db')
            
            messagebox.showinfo("成功", "数据库恢复成功！\n请重启应用程序以应用更改。")
            
        except Exception as e:
            messagebox.showerror("错误", f"数据库恢复失败：{str(e)}")
    
    def initialize_data(self):
        """数据初始化功能：保留用户相关数据，删除其他所有数据"""
        try:
            # 确认初始化操作
            if not messagebox.askyesnocancel("数据初始化确认", 
                              "警告：数据初始化将删除除用户数据外的所有其他数据！\n\n" +
                              "此操作不可逆，请确保已备份重要数据。\n\n" +
                              "确定要进行数据初始化吗？"):
                return
            
            # 连接数据库
            conn = sqlite3.connect('water_electricity.db')
            cursor = conn.cursor()
            
            # 开始事务
            conn.execute('BEGIN TRANSACTION')
            
            # 清空除用户表外的所有其他表
            tables_to_clear = ['properties', 'price_config', 'meter_readings', 'payments']
            for table in tables_to_clear:
                # 清空表数据
                cursor.execute(f'DELETE FROM {table}')
                # 重置自增主键
                cursor.execute(f'UPDATE SQLITE_SEQUENCE SET seq = 0 WHERE name = "{table}"')
            
            # 插入默认收费标准
            import datetime
            cursor.execute('''
                INSERT INTO price_config (property_type, water_price, electricity_price, effective_date)
                VALUES 
                ('门面', 6, 1.1, ?),
                ('办公室', 5, 0.9, ?)
            ''', (datetime.datetime.now().strftime("%Y-%m-%d"), datetime.datetime.now().strftime("%Y-%m-%d")))
            
            # 提交事务
            conn.commit()
            conn.close()
            
            messagebox.showinfo("成功", "数据初始化成功！\n请重启应用程序以应用更改。")
            
        except Exception as e:
            # 发生错误时回滚事务
            if conn:
                conn.rollback()
                conn.close()
            messagebox.showerror("错误", f"数据初始化失败：{str(e)}")